Warum scheitern sehr große Stack-Zuweisungen trotz unbegrenzter ulimit?

8

Die folgende statische Zuweisung ergibt einen Segmentierungsfehler

%Vor%

Aber die folgende dynamische Zuweisung geht gut

%Vor%

Die ulimit ist in Linux unbegrenzt festgelegt.

Kann mir jemand einen Hinweis geben, was passiert?

    
Anup Buchke 16.03.2013, 10:59
quelle

4 Antworten

5

Wenn Sie sagen, dass ulimit auf unbegrenzt gesetzt ist, verwenden Sie die Option -s ? Andernfalls ändert sich das Stacklimit nicht, nur die Dateigröße ist begrenzt.

Es scheint jedoch trotzdem Stapellimits zu geben. Ich kann zuweisen:

%Vor%

Und das Ausführen der Binärdatei bekomme ich:

%Vor%

Jedoch, wenn ich auf dem Stapel zuteile, ist es:

%Vor%

Was eindeutig nicht korrekt ist (was auf einen Überlauf hindeutet). Mit den ursprünglichen Zuordnungen ergeben die beiden die gleichen Ergebnisse:

%Vor%

Beim Ausführen der Stack-Version kann ich jedoch keinen segfault erzeugen, unabhängig von der Größe des Arrays - auch wenn es mehr ist als der Gesamtspeicher auf dem System, wenn -s unlimited gesetzt ist.

BEARBEITEN:

Ich habe einen Test mit malloc in einer Schleife gemacht, bis es fehlgeschlagen ist:

%Vor%

Die Stack-Nutzung erreicht jedoch nie mehr als 4 GB.

    
teppic 16.03.2013, 12:39
quelle
3

Angenommen, Ihre Maschine hat tatsächlich genug freien Speicher, um 3,125 GiB Daten zuzuordnen, liegt der Unterschied wahrscheinlich in der Tatsache, dass die statische Zuweisung all diesen Speicher benötigt, um zusammenhängend zu sein (es ist eigentlich ein 3-dimensionales Array) Die dynamische Zuweisung benötigt nur zusammenhängende Blöcke von ungefähr 2048 * 8 = 16 KiB (es ist ein Array von Zeigern auf Arrays von Zeigern auf ziemlich kleine tatsächliche Arrays).

Es ist auch möglich, dass Ihr Betriebssystem Auslagerungsdateien für Heap-Speicher verwendet, wenn es ausläuft, aber nicht für den Stack-Speicher.

    
JSQuareD 16.03.2013 11:49
quelle
2

Es gibt eine sehr gute Diskussion über das Linux-Speichermanagement - und speziell den Stack - hier: 9.7 Stack overflow , es lohnt sich das Lesen.

Sie können diesen Befehl verwenden, um herauszufinden, was Ihr aktueller Stapel soft limit ist

%Vor%

Unter Mac OS X ist das Hardlimit 64 MB, siehe Wie ändere ich die Stapelgröße mit ulimit oder pro Prozess unter Mac OS X für ein C- oder Ruby-Programm?

Sie können das Stack-Limit zur Laufzeit in Ihrem Programm ändern, siehe Ändere während der Kompilierung mit dem GNU-Compiler die Stapelgröße für eine C ++ - Anwendung in Linux

Ich habe Ihren Code mit der Probe dort kombiniert, hier ist ein Arbeitsprogramm

%Vor%     
amdn 16.03.2013 16:34
quelle
-3

Sie treffen ein Limit des Stapels. In Windows ist der Stack standardmäßig 1 MB groß, kann jedoch bei ausreichendem Speicherbedarf noch erweitert werden.

Auf vielen * nix-Systemen ist die Standard-Stack-Größe 512K.

Sie versuchen, 2048 * 2048 * 100 * 8 Bytes zuzuordnen, was über 2 ^ 25 (über 2G für Stapel) ist. Wenn Sie viel virtuellen Arbeitsspeicher zur Verfügung haben und dies immer noch auf dem Stack zuweisen möchten, verwenden Sie ein anderes Stack-Limit, während Sie die Anwendung verknüpfen.

Linux: Wie wird die Größe des ausführbaren GCC-Stacks erhöht? Ändern Sie die Stapelgröße für ein C ++ Anwendung in Linux während der Kompilierung mit GNU-Compiler

Windows: Ссылка

    
Valeri Atamaniouk 16.03.2013 11:53
quelle

Tags und Links