Was ist der Sinn von malloc(0)?

Lesezeit: 9 Minuten

Benutzeravatar von jldupont
jldupont

Ich habe das gerade gesehen Code:

artist = (char *) malloc(0);

… und ich habe mich gefragt, warum man das tun sollte?

  • verwandt: stackoverflow.com/questions/1073157/zero-size-malloc

    – Schodanex

    8. Januar 2010 um 7:58 Uhr

Gemäß den Spezifikationen, malloc(0) gibt entweder “einen Nullzeiger oder einen eindeutigen Zeiger zurück, der erfolgreich an free() übergeben werden kann”.

Auf diese Weise können Sie im Grunde nichts zuweisen, aber dennoch die Variable “Künstler” ohne Bedenken an einen Aufruf von free() übergeben. Aus praktischen Gründen ist es so ziemlich dasselbe wie:

artist = NULL;

  • Persönlich denke ich, dass das Setzen auf NULL eine bessere plattformübergreifende Strategie ist, da free() (per Spezifikation) garantiert gut mit NULL als Eingabe funktioniert.

    – Reed Copsey

    7. Januar 2010 um 17:50 Uhr

  • Wie von C. Ross erwähnt, könnten einige Plattformen technisch gesehen hier einen Zeiger zurückgeben (das ist ein “eindeutiger Zeiger, der an frei übergeben werden kann”), aber wenn Sie dies als char* behandeln, kann Ihnen das einen geben ungültiges, nicht abgeschlossenes Zeichen Es könnte gefährlich sein, sich in plattformübergreifenden Situationen darauf zu verlassen.

    – Reed Copsey

    7. Januar 2010 um 17:51 Uhr

  • Ich wünschte wirklich, die Spezifikationen würden auch “sicher an realloc übergeben” sagen -.-

    – Hansenrik

    13. Juli 2015 um 14:59 Uhr

  • @NSAddict “leere Struktur, in der sizeof 0 zurückgibt”, geben Sie bitte ein Beispiel an, klingt nach einer Spracherweiterung.

    – chux – Wiedereinsetzung von Monica

    12. September 2016 um 22:33 Uhr

  • @hanshenrik Wer sagt, dass du das nicht kannst? realloc() ermöglicht es Ihnen, jeden gültigen Zeiger zu übergeben, der von zurückgegeben wird malloc(). Sollte genug sein.

    – glglgl

    3. April 2019 um 11:18 Uhr


Benutzeravatar von Alok Singhal
Alok Singhal

Der C-Standard (C17 7.22.3/1) sagt:

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 ob die Größe ein Wert ungleich Null wäre, außer dass der zurückgegebene Zeiger nicht verwendet werden soll, um auf ein Objekt zuzugreifen.

So, malloc(0) zurückkehren könnte NULL oder ein gültiger Zeiger das darf nicht dereferenziert werden. In jedem Fall ist es vollkommen gültig, zu callen free() darauf.

Ich denke nicht wirklich malloc(0) hat viel Nutzen, außer in Fällen, in denen malloc(n) wird zum Beispiel in einer Schleife aufgerufen, und n könnte null sein.

Wenn ich mir den Code im Link ansehe, glaube ich, dass der Autor zwei Missverständnisse hatte:

  • malloc(0) gibt einen gültigen Zeiger zurück stetsund
  • free(0) ist schlecht.

Also hat er dafür gesorgt artist und andere Variablen hatten immer einen “gültigen” Wert in sich. Der Kommentar sagt so viel: // these must always point at malloc'd data.

  • Die Tatsache, dass es implementierungsabhängig ist, macht es mehr oder weniger völlig nutzlos – dies ist einer der beschisseneren Teile des C-Standards, und einige der Standardkomitees (z. B. PJ Plauger) haben darüber gestöhnt.

    anon

    7. Januar 2010 um 17:56 Uhr

  • Ich stimme zu. Wenn malloc(0) hat dann einen gültigen Zeiger zurückgegeben malloc() Rückkehr NULL bedeutet immer “Scheitern”, und 0 ist kein Sonderfall mehr, was konsequenter ist.

    – Alok Singhal

    7. Januar 2010 um 17:57 Uhr

  • Da die Umstände von malloc Fehler beim Abrufen von Speicher implementierungsdefiniert sind, könnte eine Implementierung einfach definieren, dass Zuweisungen von Größe 0 immer unerfüllbar sind (ENOMEM), und nun malloc(0) Rückgabe von 0 (mit errno==ENOMEM) ist konsistent. 🙂

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    6. September 2011 um 3:53 Uhr

  • Können Sie realloc ein Zeiger, der von zurückgegeben wird malloc(0)? Können Sie realloc((char*)NULL)?

    – Braden Best

    7. August 2016 um 21:21 Uhr

  • @Braden Am besten Ja zu beiden.

    – chux – Wiedereinsetzung von Monica

    12. September 2016 um 22:35 Uhr

Benutzeravatar von Coincoin
Münze

Das Verhalten von malloc(0) ist implementierungsspezifisch. Die Bibliothek kann NULL zurückgeben oder das reguläre malloc-Verhalten haben, ohne zugewiesenen Speicher. Was auch immer es tut, es muss irgendwo dokumentiert werden.

Normalerweise gibt es einen Zeiger zurück, der gültig und eindeutig ist, aber NICHT dereferenziert werden sollte. Beachten Sie auch, dass es Speicher verbrauchen kann, obwohl es nichts zugewiesen hat.

Es ist möglich, einen Nicht-Null-malloc(0)-Zeiger neu zuzuordnen.

Ein wörtliches malloc(0) zu haben, nützt jedoch nicht viel. Es wird meistens verwendet, wenn eine dynamische Zuweisung null Byte ist und Sie sie nicht validieren wollten.

  • malloc() muss irgendwo “Verwaltungsinformationen” aufbewahren (beispielsweise diese Größe des zugewiesenen Blocks und andere Hilfsdaten). Also, wenn malloc(0) kehrt nicht zurück NULLwird es Speicher verwenden, um diese Informationen zu speichern, und wenn nicht free()d, wird ein Speicherleck darstellen.

    – Alok Singhal

    7. Januar 2010 um 18:00 Uhr

  • Malloc-Implementierungen führen Aufzeichnungen durch, die eine bestimmte Datenmenge pro zurückgegebenem Zeiger zusätzlich zu der angeforderten Größe hinzufügen könnten.

    – Benutzer7116

    7. Januar 2010 um 18:02 Uhr

  • Verbrauchter Speicher und zugewiesener Speicher bedeuten nicht dasselbe. In genau diesem Fall geben die meisten Implementierungen einen eindeutigen Zeiger zurück. Dies bedeutet, dass ein Teil des Adressraums für diesen Zeiger geopfert werden muss. Je nach Zuweisung kann dies tatsächlich bedeuten, dass 1 Byte oder mehr zugewiesen wird.

    – Coincoin

    7. Januar 2010 um 18:02 Uhr

  • Die Bibliothek kann machen, was sie will – Nun, es kann entweder einen eindeutigen Zeiger zurückgeben, der kein anderer ist malloc() wird zurückkehren oder zurückkehren NULL.

    – Alok Singhal

    7. Januar 2010 um 18:07 Uhr

  • @jldupont: Zumindest gibt die Microsoft C-Laufzeitbibliothek einen eindeutigen Zeiger für zurück malloc(0). Jedoch in der gleichen Implementierung der Standard-C-Bibliothek, realloc(ptr, 0) befreit ptr und gibt NULL zurück.

    – Medinoc

    12. April 2018 um 14:05 Uhr

An anderer Stelle auf dieser Seite gibt es eine Antwort, die beginnt “malloc(0) gibt eine gültige Speicheradresse zurück und deren Bereich hängt von der Art des Zeigers ab, dem Speicher zugewiesen wird”. Diese Aussage ist falsch (ich habe nicht genug Ruf, um diese Antwort direkt zu kommentieren, daher kann ich diesen Kommentar nicht direkt darunter platzieren).

Das Ausführen von malloc(0) wird nicht Speicher automatisch in der richtigen Größe zuweisen. Die malloc-Funktion weiß nicht, in was Sie ihr Ergebnis umwandeln. Die malloc-Funktion stützt sich ausschließlich auf die Größenzahl, die Sie als Argument angeben. Sie müssen malloc(sizeof(int)) ausführen, um genügend Speicherplatz für ein int zu erhalten, z. B. nicht 0.

Hier gibt es viele halbwahre Antworten, also hier die harten Fakten. Die Manpage für malloc() sagt:

Wenn size 0 ist, gibt malloc() entweder NULL oder einen eindeutigen Zeigerwert zurück, der später erfolgreich an free() übergeben werden kann.

Das heißt, es gibt absolut keine Garantie, dass das Ergebnis von malloc(0) ist entweder eindeutig oder nicht NULL. Die einzige Garantie ergibt sich aus der Definition von free()hier ist, was die Manpage sagt:

Wenn ptr NULL ist, wird keine Operation ausgeführt.

Was auch immer malloc(0) zurückkehrt, kann es sicher weitergegeben werden free(). Aber das kann auch a NULL Zeiger.

Folglich schreiben artist = malloc(0); ist in keiner Weise besser als zu schreiben artist = NULL;

  • Schade, dass die Implementierung keinen Nicht-Null-, nicht eindeutigen Zeiger zurückgeben darf. Dieser Weg, malloc(0) könnte zurückgeben, sagen wir, 0x1, und free() könnte eine Sonderfallprüfung von 0x1 haben, genau wie für 0x0.

    – Todd Lehmann

    21. August 2015 um 7:24 Uhr

  • @Todd Lehman Eine Implementierung kann das tun, was Sie vorschlagen. Die C-Spezifikation gibt nicht an, dass das Ergebnis “NULL, oder ein eindeutiger Zeiger”. stattdessen ‘entweder ein Nullzeiger oder ein Zeiger auf den zugewiesenen Speicherplatz”. Es gibt kein einzigartig Erfordernis. OTOH, die Rückgabe eines nicht eindeutigen Sonderwerts kann Code stören, der auf eindeutige Werte setzt. Vielleicht eine Eckfallfrage für SO.

    – chux – Wiedereinsetzung von Monica

    12. September 2016 um 22:44 Uhr

  • man kann auch die in *nix verwendete implementierungsdefinierte Form dokumentieren. In diesem Fall nicht, aber es ist immer noch keine kanonische Quelle für General C.

    – Ludin

    28. Januar 2019 um 10:01 Uhr

  • @Lundin Stimmt. Aber die Manpages sind viel zugänglicher als der C-Standard, und die Manpages auf GNU/Linux-Systemen dokumentieren im Allgemeinen ziemlich gut, welchen Standards die Implementierung folgt. Zusammen mit der Information, welche Teile welcher Norm entsprechen, falls sie sich unterscheiden sollten. Ich habe das Gefühl, dass sie beide präzise sein wollen und jedes einzelne Bit anpreisen, das eine GNU-Erweiterung ist …

    – Cmaster – Wiedereinsetzung von Monica

    28. Januar 2019 um 20:04 Uhr

Benutzeravatar von Steve Jessop
Steve Jessop

malloc(0) macht für mich keinen Sinn, es sei denn, der Code stützt sich auf ein Verhalten, das für die Implementierung spezifisch ist. Wenn der Code portabel sein soll, dann muss er berücksichtigen, dass ein NULL zurückkommt malloc(0) ist kein Versagen. Warum also nicht einfach NULL zuweisen artist wie auch immer, da dies ein gültiges erfolgreiches Ergebnis ist und weniger Code ist und Ihre Wartungsprogrammierer keine Zeit brauchen, um es herauszufinden?

malloc(SOME_CONSTANT_THAT_MIGHT_BE_ZERO) oder malloc(some_variable_which_might_be_zero) könnten vielleicht ihren Nutzen haben, obwohl Sie wiederum besonders darauf achten müssen, eine NULL-Rückgabe nicht als Fehler zu behandeln, wenn der Wert 0 ist, aber eine Größe von 0 sollte in Ordnung sein.

  • Schade, dass die Implementierung keinen Nicht-Null-, nicht eindeutigen Zeiger zurückgeben darf. Dieser Weg, malloc(0) könnte zurückgeben, sagen wir, 0x1, und free() könnte eine Sonderfallprüfung von 0x1 haben, genau wie für 0x0.

    – Todd Lehmann

    21. August 2015 um 7:24 Uhr

  • @Todd Lehman Eine Implementierung kann das tun, was Sie vorschlagen. Die C-Spezifikation gibt nicht an, dass das Ergebnis “NULL, oder ein eindeutiger Zeiger”. stattdessen ‘entweder ein Nullzeiger oder ein Zeiger auf den zugewiesenen Speicherplatz”. Es gibt kein einzigartig Erfordernis. OTOH, die Rückgabe eines nicht eindeutigen Sonderwerts kann Code stören, der auf eindeutige Werte setzt. Vielleicht eine Eckfallfrage für SO.

    – chux – Wiedereinsetzung von Monica

    12. September 2016 um 22:44 Uhr

  • man kann auch die in *nix verwendete implementierungsdefinierte Form dokumentieren. In diesem Fall nicht, aber es ist immer noch keine kanonische Quelle für General C.

    – Ludin

    28. Januar 2019 um 10:01 Uhr

  • @Lundin Stimmt. Aber die Manpages sind viel zugänglicher als der C-Standard, und die Manpages auf GNU/Linux-Systemen dokumentieren im Allgemeinen ziemlich gut, welchen Standards die Implementierung folgt. Zusammen mit der Information, welche Teile welcher Norm entsprechen, falls sie sich unterscheiden sollten. Ich habe das Gefühl, dass sie beide präzise sein wollen und jedes einzelne Bit anpreisen, das eine GNU-Erweiterung ist …

    – Cmaster – Wiedereinsetzung von Monica

    28. Januar 2019 um 20:04 Uhr

Benutzeravatar von Shipof123
Versand von123

Warum du das nicht tun solltest…

Da der Rückgabewert von malloc von der Implementierung abhängt, erhalten Sie möglicherweise einen NULL-Zeiger oder eine andere Adresse zurück. Dies kann zu Heap-Pufferüberläufen führen, wenn der Fehlerbehandlungscode nicht sowohl die Größe als auch den zurückgegebenen Wert überprüft, was zu Stabilitätsproblemen (Abstürzen) oder noch schlimmeren Sicherheitsproblemen führt.

Betrachten Sie dieses Beispiel, in dem ein weiterer Zugriff auf den Speicher über die zurückgegebene Adresse den Heap beschädigt, wenn die Größe Null ist und die Implementierung einen Nicht-NULL-Wert zurückgibt.

size_t size;
 
/* Initialize size, possibly by user-controlled input */
 
int *list = (int *)malloc(size);
if (list == NULL) {
  /* Handle allocation error */
}
else {
  /* Continue processing list */
}

Sehen diese Seite zur sicheren Codierung von CERT Coding Standards, wo ich das obige Beispiel zur weiteren Lektüre genommen habe.

1423940cookie-checkWas ist der Sinn von malloc(0)?

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

Privacy policy