it-swarm.com.de

was ist der malloc (0)?

Habe gerade diesen Code gesehen:

artist = (char *) malloc(0);

und ich wunderte mich, warum sollte man das tun?

106
jldupont

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

Dadurch können Sie im Grunde nichts zuweisen, aber die "artist" -Variable an einen Aufruf von free () übergeben, ohne sich Sorgen zu machen. Aus praktischen Gründen ist es so ziemlich das Gleiche wie:

artist = NULL;
109
Reed Copsey

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

Wenn der angeforderte Speicherplatz null ist, ist das Verhalten durch die Implementierung definiert: Entweder wird ein Nullzeiger zurückgegeben oder das Verhalten ist, als wäre die Größe etwas Wert ungleich Null, mit der Ausnahme, dass der zurückgegebene Zeiger nicht für den Zugriff auf ein Objekt verwendet werden soll.

malloc(0) könnte also NULL oder einen gültigen Zeiger zurückgeben, der nicht dereferenziert werden kann. In beiden Fällen ist es absolut zulässig, free() dort aufzurufen.

Ich glaube nicht, dass malloc(0) von großem Nutzen ist, außer in Fällen, in denen malloc(n) in einer Schleife aufgerufen wird und n Null sein kann.

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

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

Also stellte er sicher, dass artist und andere Variablen immer einen "gültigen" Wert hatten. Der Kommentar sagt so viel: // these must always point at malloc'd data.

46
Alok Singhal

das Verhalten von malloc (0) ist implementierungsspezifisch. Die Bibliothek kann NULL zurückgeben oder das normale Malloc-Verhalten haben, ohne dass Speicher zugewiesen wird. Was 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 Speicherplatz verbrauchen kann, obwohl es tatsächlich keine Zuweisungen gibt.

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

Ein malloc (0) wörtlich zu haben, ist jedoch nicht von großem Nutzen. Sie wird meistens verwendet, wenn eine dynamische Zuweisung null Byte ist und Sie nicht daran interessiert waren, sie zu bestätigen.

9
Coincoin

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 dem Zeigertyp ab, dem Speicher zugewiesen wird". Diese Aussage ist falsch (ich habe nicht genug Reputation, um diese Antwort direkt zu kommentieren, daher kann dieser Kommentar nicht direkt darunter gestellt werden).

Wenn Sie malloc (0) ausführen, wird not automatisch Speicher mit der richtigen Größe zugewiesen. Die Malloc-Funktion weiß nicht, worauf Sie das Ergebnis auswirken. Die Malloc-Funktion beruht ausschließlich auf der von Ihnen angegebenen Größe. Sie müssen malloc (sizeof (int)) ausführen, um genügend Speicherplatz für ein int zu haben, z. B. nicht 0.

4
Krellan

malloc(0) macht für mich keinen Sinn, es sei denn, der Code ist auf ein implementierungsspezifisches Verhalten angewiesen. Wenn der Code portabel sein soll, muss er die Tatsache berücksichtigen, dass eine NULL-Rückgabe von malloc(0) kein Fehler ist. Warum also nicht gleich artist NULL zuweisen, da dies ein gültiges erfolgreiches Ergebnis ist und weniger Code ist und Ihre Wartungsprogrammierer sich nicht die Zeit nehmen müssen, um es herauszufinden?

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

3
Steve Jessop

Hier gibt es viele halbwegs richtige Antworten, also hier die harten Fakten. Die Manpage zu malloc() sagt:

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

Das heißt, es gibt absolut keine Garantie dafür, dass das Ergebnis von malloc(0) entweder eindeutig oder nicht NULL ist. Die einzige Garantie wird durch die Definition von free() gegeben. Auch hier heißt es auf der Manpage:

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

Was auch immer malloc(0) zurückgibt, kann sicher an free() übergeben werden. Aber auch ein NULL-Zeiger.

Folglich ist das Schreiben artist = malloc(0); in keiner Weise besser als das Schreiben artist = NULL;

3
cmaster

Zugegeben, ich habe das noch nie zuvor gesehen, dies ist das erste Mal, dass ich diese Syntax gesehen habe, man könnte sagen, ein klassischer Fall von Funktionsüberschuß. In Verbindung mit Reeds Antwort möchte ich darauf hinweisen, dass es eine ähnliche Sache gibt, die wie eine überladene Funktion aussieht realloc:

  • foo ist nicht NULL und die Größe ist null, realloc(foo, size);. Wenn Sie einen nicht-NULL-Zeiger und eine Größe von Null an Realloc übergeben, verhält sich Realloc so, als hätten Sie free (…) aufgerufen.
  • foo ist NULL und die Größe ist ungleich Null und größer als 1, realloc(foo, size);. Wenn Sie einen NULL-Zeiger übergeben und die Größe nicht Null ist, verhält sich Realloc so, als hätten Sie malloc (...) aufgerufen.

Hoffe das hilft, Mit freundlichen Grüßen Tom.

2
t0mm13b

Warum sollten Sie das nicht tun ...

Da der Rückgabewert von malloc von der Implementierung abhängt, erhalten Sie möglicherweise einen NULL-Zeiger oder eine andere Adresse. Dies kann am Ende zu Heap-Puffer-Überläufen führen, wenn der Fehlerbehandlungscode nicht die Größe und den zurückgegebenen Wert überprüft, was zu Stabilitätsproblemen (Abstürzen) oder sogar 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 Wert zurückgibt, der nicht NULL ist.

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 */
}

Siehe this Secure Coding Page von CERT Coding Standards, wo ich das obige Beispiel zur weiteren Lektüre nahm.

2
auselen

Um die gestellte Frage tatsächlich zu beantworten: gibt es keinen Grund dafür

1
Paolo

Unter Windows:

  • void *p = malloc(0); weist dem lokalen Heap einen Puffer mit Länge Null zu. Der zurückgegebene Zeiger ist ein gültiger Heap-Zeiger.
  • malloc ruft schließlich HeapAlloc mit dem Standard-C-Laufzeitheap auf, der dann RtlAllocateHeap aufruft.
  • free(p); verwendet HeapFree, um den Puffer mit der Länge 0 auf dem Heapspeicher freizugeben. Andernfalls würde dies zu einem Speicherverlust führen.
0
sam msft

malloc (0) gibt NULL oder einen gültigen Zeiger zurück, der zu Recht an free übergeben werden kann. Und obwohl es so aussieht, als sei die Erinnerung, auf die es verweist, unbrauchbar oder kann nicht beschrieben oder gelesen werden, ist dies nicht immer wahr. :)

int *i = malloc(0);
*i = 100;
printf("%d", *i);

Wir erwarten hier einen Segmentierungsfehler, aber überraschenderweise werden 100 ausgegeben! Das liegt daran, dass Malloc tatsächlich nach einem riesigen Speicherplatz fragt, wenn wir Malloc zum ersten Mal aufrufen. Jeder Aufruf an Malloc danach verwendet den Speicher dieses großen Blocks. Erst nachdem das riesige Stück vorüber ist, wird nach neuem Speicher gefragt.

Verwendung von malloc (0): Wenn Sie sich in einer Situation befinden, in der nachfolgende malloc-Aufrufe schneller sein sollen, sollte der Aufruf von malloc (0) dies für Sie tun (außer bei Edge-Fällen).

0
Sagar Bhosale

Es ist eigentlich ziemlich nützlich, und (offensichtlich IMHO) ist das erlaubte Verhalten, einen NULL-Zeiger zurückzugeben, fehlerhaft. Ein dynamischer Zeiger ist nicht nur nützlich für das, worauf er zeigt, sondern auch für die Tatsache, dass seine Adresse eindeutig ist. Wenn Sie NULL zurückgeben, wird diese zweite Eigenschaft entfernt. Alle eingebetteten Mallocs, die ich programmiere (ziemlich häufig), haben dieses Verhalten.

0
Scott Franco