Unter welchen Umständen kann malloc NULL zurückgeben?

Lesezeit: 8 Minuten

Benutzeravatar von RanZilber
RanZilber

Das ist mir noch nie passiert, und ich programmiere jetzt schon seit Jahren.

Kann mir jemand ein Beispiel für ein nicht-triviales Programm geben, in dem malloc geht eigentlich nicht?

Ich spreche nicht von Gedächtniserschöpfung: Ich suche nach dem einfachen Fall, wenn Sie nur einen Speicherblock in einer vom Benutzer angegebenen gebundenen Größe zuweisen, sagen wir eine ganze Zahl, verursacht malloc Versagen.

  • Hier die meisten Antworten in weniger als 2 Minuten gewinnen 🙂

    – Michael Dorgan

    1. Februar 2012 um 19:05 Uhr

  • @MichaelDorgan – es mag für Sie einfach sein, aber alle meine nicht trivialen Apps mit Malloc-Problemen wurden an Kunden geliefert, und daher kann ich sie nicht veröffentlichen 🙂

    – Martin Jakob

    1. Februar 2012 um 19:13 Uhr

  • Wenn Sie einen einzelnen Block mit begrenzter Größe zuweisen, und Ihre Grenze ist klein genug, Ihr System kann immer den Speicher bereitstellen, natürlich wird es immer gelingen. In diesem Fall jedoch Ihr One-Allocation-Toy-Programm ist trivial.

    – Nicht zu gebrauchen

    1. Februar 2012 um 19:14 Uhr

  • Lol – Ich habe so viele Jahre auf Handheld-Plattformen gearbeitet, dass NULL von malloc für mich ziemlich einfach zu erreichen ist.

    – Michael Dorgan

    1. Februar 2012 um 19:15 Uhr

  • @Useless – Wenn Sie im Laufe der Zeit Speicher verlieren oder ihn einfach wie verrückt fragmentieren, ist kein Malloc jeglicher Größe jemals vollständig sicher.

    – Michael Dorgan

    1. Februar 2012 um 19:17 Uhr

Benutzeravatar von paxdiablo
paxdiablo

Sie müssen in eingebetteten Systemen etwas arbeiten, dort erhalten Sie häufig NULL zurückgegeben 🙂

In modernen Massive-Address-Space-and-Backing-Store-Systemen ist es viel schwieriger, nicht mehr genug Arbeitsspeicher zu haben, aber in Anwendungen, in denen Sie große Datenmengen verarbeiten, wie GIS oder In-Memory-Datenbanken, oder an Orten, an denen Ihre Fehlerhafter Code führt zu einem Speicherleck.

Aber es spielt wirklich keine Rolle, ob Sie es noch nie zuvor erlebt haben – die Norm sagt, dass es passieren kann, also sollten Sie damit rechnen. Ich bin in den letzten Jahrzehnten auch nicht von einem Auto angefahren worden, aber das bedeutet nicht, dass ich über Straßen laufe, ohne vorher nachzusehen.

Und nochmal deine Bearbeitung:

Ich spreche nicht von Gedächtniserschöpfung, …

genau dieses Definition der Gedächtniserschöpfung ist malloc nicht den gewünschten Platz geben. Es ist unerheblich, ob dies durch die Zuweisung des gesamten verfügbaren Speichers oder durch Heap-Fragmentierung verursacht wird, was bedeutet, dass Sie keinen zusammenhängenden Block erhalten können, obwohl die Gesamtheit aller freien Blöcke im Speicherbereich höher ist, oder ob Sie Ihre Adressraumnutzung künstlich einschränken, z. B. mithilfe der standardkonformen Funktion :

void *malloc (size_t sz) { return NULL; }

Der C-Standard unterscheidet nicht zwischen Modi des Scheiterns, nur dass es gelingt oder fehlschlägt.

  • Das Poster fragte, ob es einen Fall gibt, in dem malloc() 0 zurückgibt und der Speicher NICHT erschöpft ist. Der Fall der Fragmentierung wird viel amüsanter, aber es braucht nicht-trivialen Code (der auf einen bestimmten Allokator abgestimmt ist), um das Muster zu zeigen.

    – Brian Bulkowski

    11. September 2014 um 6:51 Uhr

  • Brian, ich denke, das ist in meiner Antwort enthalten. Gedächtniserschöpfung ist definiert als malloc dir nicht geben zu können, was du willst. Ob Sie wirklich keinen Speicher mehr haben oder ob Sie nach 60 Byte gefragt haben und der Zuordner eine Milliarde 30-Byte-Blöcke hat, die nicht zusammengeführt werden können, spielt keine Rolle. In beiden Fällen ist es Erschöpfung. Jedenfalls A malloc das bei jedem zehnten Aufruf NULL zurückgibt, unabhängig davon, wie viel Speicher es hat (geschrieben von einem echten Sadisten), entspricht immer noch dem Standard.

    – paxdiablo

    11. September 2014 um 6:56 Uhr


Benutzeravatar von Useless
Nicht zu gebrauchen

Ja.

Versuchen Sie es einfach malloc mehr Speicher, als Ihr System bereitstellen kann (entweder durch Erschöpfung Ihres Adressraums oder durch virtuellen Speicher – je nachdem, welcher Wert kleiner ist).

malloc(SIZE_MAX)

werde es wohl machen. Wenn nicht, wiederholen Sie einige Male, bis Sie aufgebraucht sind.

  • Mein erster Computer war ein 8-Bit-System mit 56 KB RAM. malloc() ist zurückgekommen NULL zu oft.

    – Ferruccio

    1. Februar 2012 um 19:04 Uhr

  • danke, aber das ist ziemlich trivial. Ich spreche von dem einfachen Fall, dass wir Ihnen nur ein begrenztes Stück Speicher zuweisen. Kann es trotzdem scheitern? siehe meine Bearbeitung

    – RanZilber

    1. Februar 2012 um 19:06 Uhr

  • Es tut mir leid, ich hätte offensichtlich aus gutem Grund ein nicht triviales Programm posten sollen, das Hunderte von Millionen von Objekten mit vernünftiger Größe zuweist, was offensichtlich genau das gleiche Ergebnis hätte. Es ist jedoch nicht gleichzeitig lesbar, prägnant und nicht trivial!

    – Nicht zu gebrauchen

    1. Februar 2012 um 19:13 Uhr


  • Diese Antwort ist der Fall, wenn der Speicher erschöpft ist. Das Poster fragte nach einem Fall, in dem malloc() 0 zurückgibt und der Speicher NICHT erschöpft ist.

    – Brian Bulkowski

    11. September 2014 um 6:48 Uhr

  • Das wurde in die Frage eingefügt, nachdem die Antwort geschrieben wurde. Wenn Ihrer VM jedoch die Seiten ausgehen oder ein Overcommit-Limit erreicht wird oder wenn Ihrem Prozess die zusammenhängenden Adressen ausgehen, sind dies verschiedene Formen der Erschöpfung: Ich habe keine Ahnung, auf welche von ihnen “Speichererschöpfung” hinweisen soll.

    – Nicht zu gebrauchen

    11. September 2014 um 12:33 Uhr


Benutzeravatar von RussS
Russ

Jedes in C geschriebene Programm, das dynamisch mehr Speicher zuweisen muss, als das Betriebssystem derzeit zulässt.

Zum Spaß, wenn Sie Ubuntu verwenden, geben Sie ein

 ulimit -v 5000

Jedes Programm, das Sie ausführen, wird höchstwahrscheinlich abstürzen (aufgrund eines Malloc-Fehlers), da Sie die Menge an verfügbarem Speicher für einen beliebigen Prozess auf eine markige Menge begrenzt haben.

Sofern Ihr Speicher nicht bereits vollständig reserviert ist (bzw schwer fragmentiert), die einzige Möglichkeit zu haben malloc() Rückkehr a NULL-Zeiger soll Speicherplatz der Größe Null anfordern:

char *foo = malloc(0);

Zitieren aus dem C99-Standard, §7.20.3, Unterabschnitt 1:

Wenn die Größe des angeforderten Speicherplatzes null ist, ist das Verhalten implementierungsdefiniert: Entweder wird ein Nullzeiger zurückgegeben, oder das Verhalten ist so, als wäre die Größe ein Wert ungleich null, außer dass der zurückgegebene Zeiger nicht zum Zugriff auf ein Objekt verwendet werden soll.

Mit anderen Worten, malloc(0) kann a zurückgeben NULL-Zeiger oder ein gültiger Zeiger auf null zugewiesene Bytes.

Benutzeravatar von Michael Dorgan
Michael Dorgan

Wählen Sie eine beliebige Plattform, obwohl Embedded wahrscheinlich einfacher ist. malloc (oder new) eine Tonne RAM (oder RAM im Laufe der Zeit verlieren oder sogar mit naiven Algorithmen fragmentieren). Boom. malloc kehrt zurück NULL für mich gelegentlich, wenn “schlechte” Dinge passieren.

Als Antwort auf Ihre Bearbeitung. Wieder ja. Die Speicherfragmentierung im Laufe der Zeit kann dazu führen, dass sogar eine einzige Zuordnung eines int kann scheitern. Denken Sie auch daran malloc weist nicht nur 4 Bytes für an zu int, kann aber so viel Platz einnehmen, wie er möchte. Es hat seinen eigenen Buchhaltungskram und wird ziemlich oft mindestens 32-64 Bytes aufnehmen.

  • Ich mag diese Antwort, weil sie über Speicherfragmentierung und Buchhaltung spricht. Nur weil [physical] Speicher “dort” bedeutet nicht, dass er immer “verfügbar” ist. Das ist ein, malloc kann schlagen sogar fehl, wenn weniger Daten zugewiesen sind als der Gesamtspeicher. (Mir gefällt auch die ergänzende Antwort zu virtuellem Speicher und Überbelegung.)

    Benutzer166390

    1. Februar 2012 um 19:22 Uhr


  • Bist du dir sicher? Können Sie bitte sehen: stackoverflow.com/questions/29613162/…

    – Koray Tugay

    13. April 2015 um 19:25 Uhr

Benutzeravatar von Hot Licks
Heiße Licks

Auf einem mehr oder weniger Standardsystem mit einem Standard-Malloc mit einem Parameter gibt es drei mögliche Fehlermodi (die mir einfallen):

1) Die angeforderte Zuteilungsgröße ist nicht zulässig. Manche Systeme erlauben z. B. keine Zuweisung > 16 MB, selbst wenn mehr Speicher verfügbar ist.

2) Ein zusammenhängender freier Bereich der angeforderten Größe mit Standardgrenze kann nicht in der Halde lokalisiert werden. Es mag noch viel Haufen geben, aber einfach nicht genug in einem Stück.

3) Der gesamte zugeordnete Heap hat eine “künstliche” Grenze überschritten. Beispielsweise kann es dem Benutzer untersagt sein, mehr als 100 MB zuzuweisen, selbst wenn 200 MB frei und für das “System” in einem einzigen kombinierten Heap verfügbar sind.

(Natürlich können Sie Kombinationen aus 2 und 3 erhalten, da einige Systeme dem Heap nicht zusammenhängende Adressraumblöcke zuweisen, wenn dieser wächst, wodurch die „Heap-Größenbeschränkung“ auf die Gesamtzahl der Blöcke gesetzt wird.)

Beachten Sie, dass einige Umgebungen zusätzliche Malloc-Parameter wie Ausrichtung und Pool-ID unterstützen, die ihre eigenen Wendungen hinzufügen können.

  • Ich mag diese Antwort, weil sie über Speicherfragmentierung und Buchhaltung spricht. Nur weil [physical] Speicher “dort” bedeutet nicht, dass er immer “verfügbar” ist. Das ist ein, malloc kann schlagen sogar fehl, wenn weniger Daten zugewiesen sind als der Gesamtspeicher. (Mir gefällt auch die ergänzende Antwort zu virtuellem Speicher und Überbelegung.)

    Benutzer166390

    1. Februar 2012 um 19:22 Uhr


  • Bist du dir sicher? Können Sie bitte sehen: stackoverflow.com/questions/29613162/…

    – Koray Tugay

    13. April 2015 um 19:25 Uhr

Benutzeravatar von Bo Persson
Bo Persson

Überprüfen Sie einfach die Handbuchseite von malloc.

Bei Erfolg ein Zeiger auf den von der Funktion zugewiesenen Speicherblock.
Der Typ dieses Zeigers ist immer void*, der in den gewünschten Datenzeigertyp umgewandelt werden kann, um dereferenzierbar zu sein.
Wenn die Funktion den angeforderten Speicherblock nicht zuordnen konnte, wird ein Nullzeiger zurückgegeben.

  • Dies beschreibt den Vertrag, aber Wann kann/wird es passieren? (“… ist mir noch nie passiert … nicht triviales Programm, in dem malloc eigentlich nicht funktioniert? … wenn Sie nur einen Speicherblock in einer vom Benutzer angegebenen begrenzten Größe zuweisen … ist es noch möglich dass malloc scheitern wird?”)

    Benutzer166390

    1. Februar 2012 um 19:13 Uhr


  • Das ist nicht einmal eine Antwort.

    – Koray Tugay

    13. April 2015 um 19:27 Uhr

1392130cookie-checkUnter welchen Umständen kann malloc NULL zurückgeben?

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

Privacy policy