Erhalten einer Stapelüberlaufausnahme beim Deklarieren eines großen Arrays

Lesezeit: 6 Minuten

Benutzeravatar von Patrick McDonald
Patrik McDonald

Der folgende Code generiert einen Stapelüberlauffehler für mich

int main(int argc, char* argv[])
{
    int sieve[2000000];
    return 0;
}

Wie kann ich das umgehen? Ich verwende Turbo C++, möchte aber meinen Code in C behalten

BEARBEITEN:

Danke für den Hinweis. Der obige Code war nur ein Beispiel, ich deklariere das Array tatsächlich in einer Funktion und nicht in sub main. Außerdem musste das Array mit Nullen initialisiert werden. Als ich malloc googelte, stellte ich fest, dass calloc perfekt für meine Zwecke war.

Malloc/calloc hat auch den Vorteil gegenüber der Zuweisung auf dem Stack, dass ich die Größe mit einer Variablen deklarieren kann.

  • Ich las “Stack Overflow Exception” und dachte mir “…? stimmt etwas mit der Seite nicht?” Ich verbringe eindeutig viel zu viel Zeit hier :-/

    – David Z

    21. Februar 2009 um 2:27 Uhr

  • Ich bin mir ziemlich sicher, dass diese Art von Frage schon einmal auf dieser Seite aufgetaucht ist, aber die Suche nach “Stapelüberlauf” ist überhaupt nicht sinnvoll

    – Patrik McDonald

    21. Februar 2009 um 2:33 Uhr

  • Ich denke, jeder einzelne C-Programmierer verschwendet viel Zeit damit, dieses Problem zum ersten Mal zu lösen.

    – MahlerFive

    21. Februar 2009 um 3:20 Uhr

  • Turbo C++ ist eine 16-Bit-Anwendung, was bedeutet, dass sie Speichersegmentierung verwendet, jedes Segment ist 64 KB groß, sodass keine Struktur größer als diese Zahl sein kann, und die gesamte Speichernutzung auf 640 KB (1 MB oder mehr mit einigen erweiterten Speichermanagern) begrenzt ist ). Warum müssen Sie einen so über 20 Jahre alten Compiler verwenden?

    – phuklv

    28. Oktober 2013 um 3:33 Uhr

  • Inzwischen haben Sie hoffentlich GCC entdeckt. Unter anderem kommt es im Bundle mit der Code::Blöcke IDE.

    – ryker

    21. August 2019 um 12:11 Uhr


Benutzeravatar von arul
Arul

Ihr Array ist viel zu groß, um in den Stapel zu passen, ziehen Sie die Verwendung des Heaps in Betracht:

int *sieve = malloc(2000000 * sizeof(*sieve));

Wenn Sie die Stapelgröße wirklich ändern möchten, schau dir mal dieses Dokument an.

Tipp: – Vergessen Sie nicht, Ihren dynamisch zugewiesenen Speicher freizugeben, wenn er nicht mehr benötigt wird.

  • Da dies C ist, müssen Sie (und sollten es auch nicht) den Rückgabewert von malloc umwandeln.

    – Aib

    23. Februar 2009 um 2:19 Uhr

  • Warum würdest du nicht das Ergebnis von malloc wirken? Müsste man es nicht aus dem Nichts* werfen, um irgendetwas damit zu tun?

    Benutzer47589

    27. Februar 2009 um 16:19 Uhr

  • @ yodaj007: Sie müssen es nicht explizit umwandeln. Da die zugewiesene Variable ebenfalls vom Typ Zeiger ist, führt die Zuweisung eine implizite Konvertierung durch.

    – jweyrich

    10. Februar 2011 um 17:45 Uhr


  • @Amy Lesen Sie dies: “Werfe ich das Ergebnis von malloc?”. Es erklärt mehrere Gründe warum nicht zu gießen malloc (oder eine der anderen Speicherzuweisungsfunktionen) in C.

    – WhozCraig

    26. August 2015 um 17:11 Uhr


  • Verwandte: C++ Canonical Q&A-Antwort, die new/delete oder std::vector für dasselbe Problem vorschlägt: Segmentierungsfehler bei großen Array-Größen

    – Peter Cordes

    5. November 2021 um 4:22 Uhr

Es gibt 3 Möglichkeiten:

  1. Array auf Heap zuweisen – verwenden malloc(), wie andere Poster vorgeschlagen haben. Vergiss nicht free() es (obwohl für main() ist nicht so wichtig – das Betriebssystem räumt den Speicher beim Beenden des Programms für Sie auf).
  2. Deklarieren Sie das Array auf Einheitenebene – es wird im Datensegment zugewiesen und für alle sichtbar (Hinzufügen von static zur Deklaration wird die Sichtbarkeit auf die Einheit beschränken).
  3. Deklarieren Sie Ihr Array als static – In diesem Fall wird es im Datensegment zugewiesen, ist aber nur in sichtbar main().

  • Ich würde es einfach statisch machen: main() sollte nur einmal aufgerufen werden, damit es keine Fallstricke gibt; kein Bedarf für malloc() hier…

    – Christoph

    21. Februar 2009 um 10:58 Uhr

Das sind etwa 7 MB Stack-Speicherplatz. In Visual Studio würden Sie /STACK:###,### verwenden, um die gewünschte Größe widerzuspiegeln. Wenn Sie wirklich einen riesigen Stack wollen (könnte ein guter Grund sein, LISP oder so etwas zu verwenden :), selbst der Heap ist auf kleine Zuweisungen beschränkt, bevor Sie gezwungen werden, VirtualAlloc zu verwenden), möchten Sie vielleicht auch Ihr PE so einstellen, dass es mit erstellt /LARGEADDRESSAAWARE (wieder der Linker von Visual Studio), aber dies konfiguriert Ihren PE-Header, damit Ihre kompilierte Binärdatei die gesamten 4 GB des 32-Bit-Adressraums adressieren kann (wenn sie in einem WOW64 ausgeführt wird). Wenn Sie wirklich massive Binärdateien erstellen, müssen Sie normalerweise auch /bigobj als zusätzlichen Linker-Parameter konfigurieren.

Und wenn Sie noch mehr Platz benötigen, können Sie die Konvention radikal verletzen, indem Sie etwas Ähnliches wie (wieder MSVCs Link) /merge: verwenden, wodurch Sie einen Abschnitt in einen anderen packen können, sodass Sie jedes einzelne Byte für einen einzelnen gemeinsamen Code verwenden können /data Abschnitt. Natürlich müssten Sie auch die SECTIONS-Berechtigungen in einer def-Datei oder mit #pgrama konfigurieren.

Verwenden Sie malloc. Überprüfen Sie alle, ob der Rückgabetyp nicht null ist. Wenn er null ist, hat Ihr System einfach nicht genug Speicher, um so viele Werte aufzunehmen.

Sie sollten es besser auf dem Heap zuweisen, nicht auf dem Stack. etwas wie

int main(int argc, char* argv[])
{
    int * sieve;
    sieve = malloc(20000);
    return 0;
}

  • Und Sieb auf NULL prüfen

    – paulm

    12. Mai 2014 um 12:26 Uhr

  • „Ich bin nur ein Sieb für dich“ – Der Zohan

    – Drachen Lord

    30. Juli 2015 um 19:19 Uhr

  • Ich glaube du meintest sieve = malloc(20000 * sizeof *sieve) – es sei denn, Ihre Plattform hat int der Größe 1 (und selbst dann würde ich diese Annahme nicht in den Code einbetten).

    – Toby Speight

    16. Mai 2018 um 16:05 Uhr

Benutzeravatar von Ivan Rubinson
Iwan Rubinson

Ihr Array ist riesig.

Es ist möglich, dass Ihr Computer oder Betriebssystem nicht so viel Speicher hat oder zuweisen möchte.


Wenn Sie unbedingt ein riesiges Array benötigen, können Sie versuchen, es dynamisch zuzuweisen (mithilfe von malloc(...)), aber dann besteht die Gefahr, dass Speicher verloren geht. Vergessen Sie nicht, den Speicher freizugeben.

Der Vorteil von malloc ist, dass es versucht, Speicher auf dem Heap statt auf dem Stack zu allokieren (daher bekommt man keinen Stack Overflow).

Sie können den von malloc zurückgegebenen Wert überprüfen, um festzustellen, ob die Zuordnung erfolgreich war oder fehlgeschlagen ist. Wenn dies fehlschlägt, versuchen Sie einfach, ein kleineres Array zu mallocen.


Eine andere Option wäre die Verwendung einer anderen Datenstruktur, deren Größe im Handumdrehen geändert werden kann (wie eine verknüpfte Liste). Ob diese Option gut ist, hängt davon ab, was Sie mit den Daten machen werden.

Eine weitere Option wäre, Dinge in einer Datei zu speichern und Daten on the fly zu streamen. Dieser Ansatz ist der langsamste.

Wenn Sie sich für die Speicherung auf der Festplatte entscheiden, können Sie auch eine vorhandene Bibliothek (für Datenbanken) verwenden.

  • Und Sieb auf NULL prüfen

    – paulm

    12. Mai 2014 um 12:26 Uhr

  • „Ich bin nur ein Sieb für dich“ – Der Zohan

    – Drachen Lord

    30. Juli 2015 um 19:19 Uhr

  • Ich glaube du meintest sieve = malloc(20000 * sizeof *sieve) – es sei denn, Ihre Plattform hat int der Größe 1 (und selbst dann würde ich diese Annahme nicht in den Code einbetten).

    – Toby Speight

    16. Mai 2018 um 16:05 Uhr

Da Turbo C/C++ ein 16-Bit-Compiler ist, verbraucht der int-Datentyp etwa 2 Bytes. 2 Byte*2000000=40.00.000 Byte=3,8147 MB ​​Speicherplatz.

Die Auto-Variablen einer Funktion werden im Stack gespeichert und verursachten den Überlauf des Stack-Speichers. Verwenden Sie stattdessen den Datenspeicher [using static or global variable] oder der dynamische Heap-Speicher [using the malloc/calloc] zum Erstellen des erforderlichen Speichers gemäß der Verfügbarkeit der Prozessorspeicherzuordnung.

1408370cookie-checkErhalten einer Stapelüberlaufausnahme beim Deklarieren eines großen Arrays

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy