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.
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
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.
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.
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.
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
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”.
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
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.
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