GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Was gibt malloc(0) zurück?

Andere haben wie malloc(0) geantwortet funktioniert. Ich werde eine der Fragen beantworten, die Sie gestellt haben und die noch nicht beantwortet wurde (glaube ich). Die Frage bezieht sich auf realloc(malloc(0), 0) :

Was bedeutet malloc(0) Rückkehr? Wäre die Antwort für realloc(malloc(0),0) dieselbe ?

Der Standard sagt dies über realloc(ptr, size) :

  • wenn ptr ist NULL , verhält es sich wie malloc(size) ,
  • ansonsten (ptr ist nicht NULL ), hebt es den alten Objektzeiger um ptr auf und gibt einen Zeiger auf einen neu zugewiesenen Puffer zurück. Aber wenn size 0 ist, sagt C89, dass der Effekt äquivalent zu free(ptr) ist . Interessanterweise kann ich diese Aussage im C99-Entwurf (n1256 oder n1336) nicht finden. In C89 wäre der einzig sinnvolle Rückgabewert in diesem Fall NULL .

Es gibt also zwei Fälle:

  • malloc(0) gibt NULL zurück auf eine Implementierung. Dann Ihr realloc() call entspricht realloc(NULL, 0) . Das entspricht malloc(0) von oben (und das ist NULL in diesem Fall).
  • malloc(0) gibt nicht-NULL zurück . Dann entspricht der Aufruf free(malloc(0)) . In diesem Fall malloc(0) und realloc(malloc(0), 0) sind nicht Äquivalent.

Beachten Sie, dass es hier einen interessanten Fall gibt:im zweiten Fall, wenn malloc(0) gibt nicht-NULL zurück bei Erfolg kann es immer noch NULL zurückgeben Misserfolg anzuzeigen. Dies führt zu einem Aufruf wie:realloc(NULL, 0) , was malloc(0) entsprechen würde , die NULL zurückgeben kann oder nicht .

Ich bin mir nicht sicher, ob die Auslassung in C99 ein Versehen ist oder ob es bedeutet, dass in C99 realloc(ptr, 0) für Nicht-NULL ptr ist nicht gleichbedeutend mit free(ptr) . Ich habe es gerade mit gcc -std=c99 versucht , und obiges entspricht free(ptr) .

Bearbeiten :Ich glaube, ich verstehe, was Ihre Verwirrung ist:

Sehen wir uns einen Ausschnitt aus Ihrem Beispielcode an:

ptr = malloc(0);
if (ptr == realloc(ptr, 1024))

Das obige ist nicht dasselbe wie malloc(0) == realloc(malloc(0), 1024) . Im zweiten die malloc() Der Aufruf erfolgt zweimal, während Sie beim ersten einen zuvor zugewiesenen Zeiger auf realloc() übergeben .

Lassen Sie uns zuerst den ersten Code analysieren. Angenommen malloc(0) gibt NULL nicht zurück bei Erfolg ptr einen gültigen Wert hat. Wenn Sie realloc(ptr, 1024) machen , realloc() gibt Ihnen im Grunde einen neuen Puffer mit der Größe 1024 und dem ptr wird ungültig. Eine konforme Implementierung kann dieselbe Adresse zurückgeben wie die bereits in ptr . Also, Ihr if Bedingung kann wahr zurückgeben. (Beachten Sie jedoch den Wert von ptr nach realloc(ptr, 1024) kann undefiniertes Verhalten sein.)

Nun die Frage, die Sie stellen:malloc(0) == realloc(malloc(0), 1024) . Nehmen wir in diesem Fall an, dass sowohl der malloc(0) auf der linken und rechten Seite gibt nicht-NULL zurück . Dann sind sie garantiert anders. Auch der Rückgabewert von malloc() auf der linken Seite war nicht free() d noch, also alle anderen malloc() , calloc() , oder realloc() gibt diesen Wert möglicherweise nicht zurück. Das bedeutet, wenn Sie Ihre Bedingung wie folgt geschrieben haben:

if (malloc(0) == realloc(malloc(0), 1024)
    puts("possible");

possible wird nicht angezeigt am Ausgang (es sei denn, sowohl malloc() und realloc() fehlschlagen und NULL zurückgeben ).

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    void *p1;
    void *p2;

    p1 = malloc(0);
    p2 = realloc(p1, 1024);
    if (p1 == p2)
        puts("possible, OK");

    /* Ignore the memory leaks */
    if (malloc(0) == realloc(malloc(0), 1024))
        puts("shouldn't happen, something is wrong");
    return 0;
}

Unter OS X hat mein Code beim Ausführen nichts ausgegeben. Unter Linux wird possible, OK ausgegeben .


malloc(0) ist Implementierung definiert was C99 betrifft.

Ab C99 [Abschnitt 7.20.3]

Die Reihenfolge und Kontinuität des Speichers, der durch aufeinanderfolgende Aufrufe der Funktionen calloc, malloc und realloc zugewiesen wird, ist nicht spezifiziert . Der bei erfolgreicher Zuordnung zurückgegebene Zeiger ist geeignet ausgerichtet, so dass er einem Zeiger auf einen beliebigen Objekttyp zugewiesen und dann verwendet werden kann, um auf ein solches Objekt oder ein Array solcher Objekte in dem zugewiesenen Speicherplatz zuzugreifen (bis der Speicherplatz explizit freigegeben wird). Die Lebensdauer eines zugewiesenen Objekts erstreckt sich von der Zuweisung bis zur Freigabe. Jede solche Zuordnung soll einen Zeiger auf ein Objekt ergeben, das von jedem anderen Objekt disjunkt ist. Der zurückgegebene Zeiger zeigt auf den Anfang (niedrigste Byteadresse) des zugewiesenen Speicherplatzes. Wenn der Speicherplatz nicht zugewiesen werden kann, wird ein Nullzeiger zurückgegeben. Wenn die Größe des angeforderten Speicherplatzes null ist, ist das Verhalten implementierungsdefiniert :Entweder wird ein Null-Zeiger 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.


In C89 ist malloc(0) implementierungsabhängig - ich weiß nicht, ob C99 dies behoben hat oder nicht. Verwenden Sie in C++:

char * p = new char[0];

wohldefiniert ist - Sie erhalten einen gültigen Nicht-Null-Zeiger. Natürlich können Sie den Zeiger nicht verwenden, um auf das zuzugreifen, worauf er zeigt, ohne undefiniertes Verhalten hervorzurufen.

Der Grund dafür ist, dass es für einige Algorithmen praktisch ist und bedeutet, dass Sie Ihren Code nicht mit Tests auf Nullwerte übersäten müssen.


Linux
  1. Was bedeutet „–“ (Doppelstrich)?

  2. Was macht „lc_all=c“?

  3. Was macht ?

  4. Was bedeutet Exec 3?

  5. Was macht . ~/.bashrc Befehl Tun??

Was macht Bamfdaemon?

Was gibt der Befehl Ls -al .* zurück?

Was macht ulimit -s unlimited?

Was genau macht init?

Was macht kill -- -0?

Was macht CAP_NET_RAW?