Ich verwende MinGW mit GCC 3.4.5 (mingw-special vista r3).
Meine C-Anwendung verwendet viel Stack, also habe ich mich gefragt, ob es eine Möglichkeit gibt, programmatisch zu sagen, wie viel Stack noch übrig ist, damit ich die Situation sauber handhaben kann, wenn ich feststelle, dass ich kurz davor bin, auszugehen.
Wenn nicht, auf welche andere Weise würden Sie das Problem umgehen, dass möglicherweise der Stapelspeicherplatz ausgeht?
Ich habe keine Ahnung, mit welcher Stapelgröße ich anfange, also müsste ich das auch programmatisch identifizieren.
Phoxie
Die Getrusage-Funktion liefert Ihnen die aktuelle Nutzung. (sehen man getrusage).
Das getrlimit unter Linux würde helfen, die Stapelgröße mit dem abzurufen RLIMIT_STACK Parameter.
#include <sys/resource.h>
int main (void)
{
struct rlimit limit;
getrlimit (RLIMIT_STACK, &limit);
printf ("\nStack Limit = %ld and %ld max\n", limit.rlim_cur, limit.rlim_max);
}
Bitte werfen Sie einen Blick auf man getrlimit. Dieselben Informationen könnten von abgerufen werden ulimit -s oder ulimit -a Stapelgröße Zeile. Schau auch mal rein setrlimit Funktion, die es ermöglichen würde, die Grenzen festzulegen. Aber wie in den anderen Antworten erwähnt, sollten Sie Ihr Design wahrscheinlich überdenken, wenn Sie den Stapel anpassen müssen. Wenn Sie ein großes Array wollen, warum nehmen Sie den Speicher nicht aus dem Heap?
getrusage() funktioniert nicht für die Stapelgröße unter Linux. “ru_isrss (unmaintained) This field is currently unused on Linux.” (linux.die.net/man/2/getrusage). Ich weiß nicht, wann es dazu kam, aber es trifft auf Kernel 2.6.28 zu.
– atz
13. Januar 2012 um 11:46 Uhr
@phoxis:getrlimit (RLIMIT_STACK, &limit)scheint die Gesamtstapelgröße anzugeben, nicht die verbleibende freie Stapelgröße.
– Benutzer2284570
19. Juli 2016 um 17:32 Uhr
@ user2284570 : Von man getrlimit Ich kann sehen, dass es geschrieben steht: “Die maximale Größe des Prozessstapels in Bytes.” . Können Sie erläutern, warum Sie glauben, dass es die verbleibende Stapelgröße sein könnte?
– phoxie
21. Juli 2016 um 12:55 Uhr
@phoxis: Das sage ich. Es ist die Gesamtstapelgröße. Und im Fall des ᴏᴘ ist nur das Erhalten des Restes nützlich.
– Benutzer2284570
22. Juli 2016 um 13:20 Uhr
Es würde funktionieren, die Adresse einer lokalen Variablen vom Stack zu nehmen. Dann können Sie in einem stärker verschachtelten Aufruf die Adresse eines anderen Lokals subtrahieren, um den Unterschied zwischen ihnen zu finden
Wenn Ihr Code Multithreading ist, müssen Sie sich damit befassen, die top_of_stack-Variable pro Thread zu speichern.
Ich mag diese Antwort, aber ohne die Größe des Stapels im Voraus zu kennen, kann ich nicht sagen, ob ich ihn in die Luft jagen werde.
– Paul Hargreaves
10. September 2008 um 12:18 Uhr
Es gibt eine Standardgröße des Stacks für Threads auf Ihrem System. Unter Windows ist dies 1 MB Adressraum. Sie können dies steuern, wenn Sie Ihre eigenen Threads erstellen. Wie Skizz betont, wäre es jedoch am besten, sich keine Gedanken über das genaue Limit machen zu müssen!
– Rob Walker
10. September 2008 um 13:16 Uhr
Dies könnte insbesondere bei MinGW in Ordnung sein. Im Allgemeinen ist nicht garantiert, dass der Stack für ein Programm zusammenhängend ist. Es ist für eine Implementierung (beispielsweise eine, die keinen virtuellen Speicher hat) zulässig, Stack-Blöcke nach Bedarf zuzuweisen und sie miteinander zu verketten. Wenn Ihre Plattform dies tut, gibt es möglicherweise nicht einmal eine standardmäßige maximale Stapelgröße für ein Programm: Sie können einfach weitermachen, bis Ihnen der freie Speicher ausgeht. Aber ein guter Grund, trotzdem ein Limit zu haben, ist, zu verhindern, dass eine außer Kontrolle geratene Rekursion das gesamte System durch Erschöpfung des Speichers zum Erliegen bringt.
– Steve Jessop
2. November 2009 um 12:15 Uhr
Unter Linux erhalten Sie die Stapelgröße mit ulimit -a.
– Mark Lakata
29. Juni 2018 um 0:35 Uhr
Warnungen: Einige Plattformen (insbesondere eingebettete Systeme) ordnen keine Daten auf dem Stack zu (nur Funktionsrückgabeadressen werden auf dem Stack gespeichert). In diesem Fall ist die Adresse lokaler Variablen bedeutungslos.
– Mark Lakata
29. Juni 2018 um 0:37 Uhr
Prüfen Sie, ob Ihr Compiler stackavail() unterstützt
Angenommen, Sie kennen die Größe des vollständigen Stapels, könnten Sie wahrscheinlich einen Assembler-Code hinzufügen, um ESP zu lesen.
Wenn Sie ESP lesen und in der Hauptfunktion beiseite speichern, können Sie das aktuelle ESP mit dem ESP vergleichen, das Sie in der Hauptfunktion haben, und sehen, wie viel ESP sich geändert hat. Das gibt Ihnen einen Hinweis darauf, wie viel Stack Sie verwendet haben.
Das ist ein Problem, das ich aufgegeben habe. Mit viel Hacking und (meistens) Beten können Sie eine Lösung erhalten, die zu einem bestimmten Zeitpunkt auf einem bestimmten Computer funktioniert. Aber im Allgemeinen scheint es keinen anständigen Weg zu geben, dies zu tun.
Sie müssen die Stapelposition und -größe von außerhalb Ihres Programms erhalten (unter Linux erhalten Sie sie möglicherweise von /proc/<pid>/maps). In Ihrem Programm müssen Sie irgendwie testen, wo Sie sich am Stack befinden. Die Verwendung lokaler Variablen ist möglich, aber es gibt keine wirkliche Garantie, dass sie sich tatsächlich auf dem Stack befinden. Sie können auch versuchen, den Wert aus dem Stapelzeigerregister mit einer Assembly zu erhalten.
Jetzt haben Sie also den Ort des Stapels, seine Größe und die aktuelle Position und gehen davon aus, dass Sie wissen, in welche Richtung der Stapel wächst. Wann gehst du in den Stack-Overflow-Modus? Machen Sie es besser nicht ganz am Ende, weil Ihre Schätzung (dh Adresse der lokalen Variablen oder Wert vom Stapelzeiger) wahrscheinlich etwas zu optimistisch ist; Es ist nicht ungewöhnlich, Speicher jenseits des Stapelzeigers zu adressieren. Außerdem haben Sie keine Ahnung, wie viel Platz auf dem Stapel eine bestimmte Funktion (und die von ihr aufgerufenen Funktionen) benötigt. Man muss also am Ende ziemlich viel Platz lassen.
Ich kann Ihnen nur raten, sich nicht in diesen Schlamassel zu begeben und zu versuchen, sehr tiefe Rekursionen zu vermeiden. Vielleicht möchten Sie auch Ihre Stapelgröße erhöhen; Unter Windows müssen Sie dies in die ausführbare Datei kompilieren, glaube ich.
botismarius
Vielleicht hilft dies nur für die Windows-Plattform:
im PE-Header (IMAGE_NT_HEADERS) Ihrer exe gibt es einige Einträge wie:
Es gibt eine einfache Möglichkeit, diese Werte zu erhalten: Die Verwendung von GetModuleHandle(NULL) gibt Ihnen die Imagebase (Handle) Ihres Moduls, Adresse, wo Sie eine IMAGE_DOS_HEADER-Struktur finden, die Ihnen hilft, die IMAGE_NT_HEADERS-Struktur zu finden (Imagebase+IMAGE_DOS_HEADER. e_lfanew) -> IMAGE_NT_HEADERS, und dort finden Sie diese Felder: SizeOfStackReserve und SizeOfStackCommit.
Die maximale Menge an Speicherplatz, die das Betriebssystem Ihrem Stack zuweist, ist SizeOfStackReserve.
Wenn Sie erwägen, dies zu versuchen, lassen Sie es mich wissen und ich werde Ihnen helfen. Es gibt eine Möglichkeit, die an einem bestimmten Punkt verwendete Stapelgröße zu erhalten.
Tim Cooper
Raymond Chen (Das Alte Neue) hat eine gute Antwort auf diese Art von Frage:
Wenn Sie fragen müssen, machen Sie wahrscheinlich etwas falsch.
Hier sind einige Win32-Details zur Stapelzuweisung: MSDN.
Wenn Sie der Meinung sind, dass Sie möglicherweise durch den Stapelspeicher begrenzt sind, werden Sie mit ziemlicher Sicherheit durch den verfügbaren virtuellen Speicher eingeschränkt sein. In diesem Fall müssen Sie eine andere Lösung finden.
Was genau versuchst du zu tun?
Ein (nicht gutes) Beispiel wäre: void subroutine(int i) { char foo[20000]; i++; wenn (i < 1000) Unterprogramm (i); }
– Paul Hargreaves
10. September 2008 um 12:57 Uhr
Du hast Recht, das ist kein gutes Beispiel. Was ich wirklich wissen wollte, war, was Sie mit dem 20k-Array machen.
– Schizz
10. September 2008 um 13:39 Uhr
Wenn Sie jedoch jemals versucht haben, wirklich tragbaren Code zu schreiben, lernen Sie, dass “Sie immer fragen müssen und immer etwas falsch machen, weil es kein tragbares Konzept der “Stack-Nutzung” gibt und es doch das des Programmierers ist Verantwortung, nicht zu viel Stack zu verwenden. Es ist also am besten, sich einfach der Verschwörung des Schweigens anzuschließen, einen Funktionstest zu schreiben, von dem Sie hoffen, dass er so viel Stack verbraucht, wie Ihr Programm jemals in der Praxis verbraucht, und es dem Plattformintegrator zu überlassen, sich darum zu kümmern”.
– Steve Jessop
2. November 2009 um 12:10 Uhr
Die Frage ist nicht “Soll ich die Stapelgröße überprüfen?” es ist “Wie überprüfe ich die Stapelgröße?”
– Gerechtigkeit
20. Mai 2018 um 18:25 Uhr
Ich möchte nur die Stapelgröße abfragen, um die Frage zu beantworten: “Werden dateibezogene Arrays auf den Stapel gelegt?” Ich nehme an, nein, aber indem ich zwei einfache Programme mache, die die Stapelgröße abfragen, eines mit und eines ohne ein dateibezogenes Array, kann ich die Frage selbst beantworten.
– KANJICODER
17. April 2020 um 21:49 Uhr
14033000cookie-checkÜberprüfen der verfügbaren Stapelgröße in Cyes