Nullgröße malloc [duplicate]

Lesezeit: 7 Minuten

Benutzeravatar von shodanex
Schodanex

Sehr einfache Frage, ich habe das folgende Programm erstellt:

#include <stdlib.h>
int main(int argc, char ** argv)
{
    void * ptr;
    ptr = malloc(0);
    free(ptr);
}

Und es segfault nicht auf meiner Maschine. Ist es ein tragbares Verhalten von stdlib malloc und kostenlos, oder suche ich nach Problemen?

Bearbeiten: Was nicht portierbar zu sein scheint, ist der von malloc zurückgegebene Wert. Die Frage bezieht sich auf die Kombination malloc(0) + free, nicht auf den Wert von ptr.

  • Denken Sie daran, dass, wenn dies nicht funktioniert, viel Code für Sonderfälle vorhanden sein müsste. Die Leute werden ständig eine Anzahl von Bytes auf der Grundlage einer Variablen oder eines Ausdrucks mallocieren, und es wäre umständlich, jedes Mal auf Null prüfen zu müssen.

    – David Thornley

    26. Oktober 2009 um 13:33 Uhr

  • verwandt: stackoverflow.com/questions/2022335/whats-the-point-in-malloc0

    – Jldupont

    7. Januar 2010 um 18:23 Uhr

  • Ich weiß: Super später Kommentar zu dieser geschlossenen Frage. Aber da ist manchmal eine Verwendung für malloc(0) das wird nicht erwähnt. Bei den Implementierungen, bei denen es einen Nicht-NULL-Wert zurückgibt, insbesondere in einem DEBUG-Build, weist es wahrscheinlich MEHR zu, als Sie angefordert haben, und gibt Ihnen den Zeiger direkt hinter seinem internen Header. Dadurch erhalten Sie eine Gefühl für die tatsächliche Speichernutzung, wenn Sie dies vor und nach einer Reihe von Zuweisungen erhalten.

    – Jesse Chisholm

    24. Februar 2017 um 17:57 Uhr

Benutzeravatar von Key
Taste

Das Verhalten ist implementierungsdefiniert, Sie erhalten entweder einen NULL-Zeiger oder eine Adresse. Das Freirufen für den empfangenen Zeiger sollte jedoch kein Problem verursachen, da:

  • free(NULL) ist ok, es wird keine Operation durchgeführt
  • free(address) ist ok, wenn Adresse von malloc (oder anderen wie calloc etc.)

  • Wenn eine Adresse zurückgegeben wird, wie groß wäre dann der Speicherblock?

    – Abhishek Jaiswal

    10. Mai 2021 um 8:22 Uhr

  • @AbhishekJaiswal es wäre null.

    – marco-a

    14. Oktober 2021 um 22:38 Uhr

Es ist erlaubt, NULL zurückzugeben, und es ist erlaubt, einen Nicht-NULL-Zeiger zurückzugeben, den Sie nicht dereferenzieren können. Beide Wege sind durch den Standard (7.20.3) sanktioniert:

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 .

  • Das ist nicht genau die gestellte Frage. Der von malloc zurückgegebene Wert interessiert mich nicht, sondern der freie Aufruf eines von malloc(0) zurückgegebenen Zeigers.

    – Schodanex

    2. Juli 2009 um 9:32 Uhr

  • Es ist immer noch eine sehr gute Antwort, da es zusammen mit der Antwort von Key einen vollständigen Überblick über das Verhalten gibt.

    – schnaader

    26. Oktober 2009 um 14:21 Uhr

  • Ich denke, es ist 7.22.3, nicht 7.20.3 – okay, die Antwort wurde also 2009 geschrieben, 🙂 Ich meinte 7.22.3 in C11

    – aqjun

    8. Mai 2018 um 8:18 Uhr


Entschuldigung für die Mühe, ich hätte die Manpages lesen sollen:

malloc() weist Größenbytes zu und gibt einen Zeiger auf den zugeordneten Speicher zurück. Der Speicher wird nicht gelöscht. Wenn size 0 ist, gibt malloc() entweder NULL oder einen eindeutigen Zeigerwert zurück, der später erfolgreich an free() übergeben werden kann.

frei() gibt den Speicherplatz frei, auf den ptr zeigt, der von einem vorherigen Aufruf von malloc(), calloc() oder realloc() zurückgegeben worden sein muss. Andernfalls oder wenn free(ptr) bereits zuvor aufgerufen wurde, tritt undefiniertes Verhalten auf. Wenn ptr NULL ist, wird keine Operation ausgeführt.

Es scheint zumindest für die gnu libc zu stimmen

Nach c-Norm

7.20.3 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 für den Zugriff verwendet werden soll ein Objekt.

Benutzeravatar von Aditya Sehgal
Aditya Sehgal

Aktualisiert unter Berücksichtigung der Kommentare von libt & Pax:

Das Verhalten beim Aufruf von malloc(0) ist implementierungsabhängig oder mit anderen Worten nicht portierbar und undefiniert.

Link zu CFaq Frage für mehr Details.

  • Die ISO-Normen unterscheiden sehr klar zwischen definiert, implementierungsdefiniert und undefiniert. Du solltest auch. Implementierungsdefiniert bedeutet es ist definiert, aber das Doco für diese Implementierung wird Ihnen sagen, was es tut. Undefiniert bedeutet, dass es möglich ist absolut alles einschließlich, aber nicht beschränkt auf die totale Zerstörung des Universums.

    – paxdiablo

    2. Juli 2009 um 8:49 Uhr

  • danke für die Klarstellung (und die Ablehnung 😉 ). Ich habe den Begriff “undefiniert” dort ziemlich locker verwendet. Mein Fehler.

    – Aditya Sehgal

    2. Juli 2009 um 16:14 Uhr

  • Du missverstehst die FAQ. Das bedeutet nicht, dass das Gesamtverhalten implementierungsdefiniert ist. Das bedeutet, dass die Implementierung definiert ist, ob das Ergebnis NULL oder ein anderer Wert ist oder nicht. Zu einem gültigen Verhalten gehört beispielsweise nicht das Senden eines sigsegv.

    – Johannes Schaub – litb

    2. Juli 2009 um 18:26 Uhr

  • @aditya, der Kommentar war von mir, die Ablehnung nicht – ich gebe den Leuten normalerweise die Möglichkeit, ihre Antwort zu bearbeiten, bevor sie sie ablehnen.

    – paxdiablo

    2. Juli 2009 um 22:58 Uhr

  • @aditya, warte. Ich habe dich auch nicht runtergestimmt 🙂

    – Johannes Schaub – litb

    3. Juli 2009 um 0:28 Uhr

Benutzeravatar von Jeffrey Walton
Jeffrey Walton

Obwohl es sich um legales C/C++ handeln könnte, weist es auf größere Probleme hin. Ich nenne es allgemein “Zeiger-Schrägheit”.

Siehe „Machen Sie keine Annahmen über das Ergebnis von malloc(0) oder calloc(0)“, https://www.securecoding.cert.org/confluence/display/seccode/VOID+MEMxx-A.+Machen+keine+Annahmen+über+das+Ergebnis+von+malloc%280%29+oder+calloc %280%29.

  • Die ISO-Normen unterscheiden sehr klar zwischen definiert, implementierungsdefiniert und undefiniert. Du solltest auch. Implementierungsdefiniert bedeutet es ist definiert, aber das Doco für diese Implementierung wird Ihnen sagen, was es tut. Undefiniert bedeutet, dass es möglich ist absolut alles einschließlich, aber nicht beschränkt auf die totale Zerstörung des Universums.

    – paxdiablo

    2. Juli 2009 um 8:49 Uhr

  • danke für die Klarstellung (und die Ablehnung 😉 ). Ich habe den Begriff “undefiniert” dort ziemlich locker verwendet. Mein Fehler.

    – Aditya Sehgal

    2. Juli 2009 um 16:14 Uhr

  • Du missverstehst die FAQ. Das bedeutet nicht, dass das Gesamtverhalten implementierungsdefiniert ist. Das bedeutet, dass die Implementierung definiert ist, ob das Ergebnis NULL oder ein anderer Wert ist oder nicht. Zu einem gültigen Verhalten gehört beispielsweise nicht das Senden eines sigsegv.

    – Johannes Schaub – litb

    2. Juli 2009 um 18:26 Uhr

  • @aditya, der Kommentar war von mir, die Ablehnung nicht – ich gebe den Leuten normalerweise die Möglichkeit, ihre Antwort zu bearbeiten, bevor sie sie ablehnen.

    – paxdiablo

    2. Juli 2009 um 22:58 Uhr

  • @aditya, warte. Ich habe dich auch nicht runtergestimmt 🙂

    – Johannes Schaub – litb

    3. Juli 2009 um 0:28 Uhr

Benutzeravatar von Ashutosh Singhal
Ashutosh Singhal

Meiner Erfahrung nach habe ich gesehen, dass malloc (0) einen Zeiger zurückgibt, der freigegeben werden kann. Dies verursacht jedoch SIGSEGV in späteren malloc()-Anweisungen. Und das war höchst zufällig.

Als ich eine Überprüfung hinzugefügt habe, um malloc nicht aufzurufen, wenn die zuzuweisende Größe Null ist, habe ich dies entfernt.

Daher würde ich vorschlagen, der Größe 0 keinen Speicher zuzuweisen.

-Aschutosch

  • ISO C erfordert Zuweisungen der Größe Null, um zu funktionieren. Sie können entweder zurückkehren NULLoder ein eindeutiger Zeiger, an den später übergeben werden kann free. Ihr Kommentar ist ohne einen minimalen Repro-Testfall und die Benennung der genauen Umgebung, in der dies passiert ist, nicht nützlich: Compiler-Version, Bibliothek, Betriebssystem.

    – Kas

    25. Oktober 2021 um 3:02 Uhr


  • Wenn ein eindeutiger Zeiger zurückgegeben wird, unterliegt er allen regulären Regeln. Sie können nicht über seinen Bereich hinaus zugreifen und das bedeutet, dass der Zeiger nicht dereferenziert werden kann: ((char *) ptr)]size] ist kein gültiges Byte, wenn ptr kam aus malloc(size)und in diesem Fall size ist 0. Außerdem können Sie es nicht zwei- oder mehrmals freigeben. Sobald Sie es freigeben, wird es unbestimmt; diese Zeiger sind anfällig für Double-Free-Fehler. Ein Programm, das davon ausgeht, dass das Ergebnis von malloc(0) kann zwei- oder mehrmals freigegeben werden, funktioniert auf einer Plattform, auf der NULL zurückgegeben wird, kann aber anderswo fehlschlagen.

    – Kas

    25. Oktober 2021 um 3:08 Uhr

1410910cookie-checkNullgröße malloc [duplicate]

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

Privacy policy