Altri hanno risposto come malloc(0)
lavori. Risponderò a una delle domande che hai posto a cui non è stata ancora data risposta (credo). La domanda riguarda realloc(malloc(0), 0)
:
Cosa significa
malloc(0)
Restituzione? La risposta sarebbe la stessa perrealloc(malloc(0),0)
?
Lo standard dice questo su realloc(ptr, size)
:
- se
ptr
èNULL
, si comporta comemalloc(size)
, - altrimenti (
ptr
non èNULL
), rilascia il vecchio puntatore all'oggetto tramiteptr
e restituisce un puntatore a un nuovo buffer allocato. Ma sesize
è 0, C89 dice che l'effetto è equivalente afree(ptr)
. È interessante notare che non riesco a trovare quella dichiarazione nella bozza C99 (n1256 o n1336). In C89, l'unico valore sensato da restituire in quel caso sarebbeNULL
.
Quindi, ci sono due casi:
malloc(0)
restituisceNULL
su un'implementazione. Poi il tuorealloc()
chiamata è equivalente arealloc(NULL, 0)
. Equivale amalloc(0)
dall'alto (e questo èNULL
in questo caso).malloc(0)
restituisce diverso daNULL
. Quindi, la chiamata equivale afree(malloc(0))
. In questo caso,malloc(0)
erealloc(malloc(0), 0)
non equivalente.
Nota che qui c'è un caso interessante:nel secondo caso, quando malloc(0)
restituisce diverso da NULL
in caso di successo, potrebbe comunque restituire NULL
per indicare il fallimento. Ciò risulterà in una chiamata del tipo:realloc(NULL, 0)
, che sarebbe equivalente a malloc(0)
, che può restituire o meno NULL
.
Non sono sicuro se l'omissione in C99 sia una svista o se significhi che in C99, realloc(ptr, 0)
per non-NULL
ptr
non è equivalente a free(ptr)
. Ho appena provato con gcc -std=c99
, e quanto sopra è equivalente a free(ptr)
.
Modifica :Penso di capire qual è la tua confusione:
Diamo un'occhiata a uno snippet del tuo codice di esempio:
ptr = malloc(0);
if (ptr == realloc(ptr, 1024))
Quanto sopra non è lo stesso di malloc(0) == realloc(malloc(0), 1024)
. Nel secondo, il malloc()
la chiamata viene effettuata due volte, mentre nella prima si passa un puntatore allocato in precedenza a realloc()
.
Analizziamo prima il primo codice. Supponendo malloc(0)
non restituisce NULL
in caso di successo, ptr
ha un valore valido Quando esegui realloc(ptr, 1024)
, realloc()
fondamentalmente ti dà un nuovo buffer che ha la dimensione 1024 e il ptr
diventa invalido. Un'implementazione conforme può restituire lo stesso indirizzo di quello già presente in ptr
. Quindi, il tuo if
la condizione può restituire true. (Nota, tuttavia, osservando il valore di ptr
dopo realloc(ptr, 1024)
potrebbe essere un comportamento non definito.)
Ora la domanda che fai:malloc(0) == realloc(malloc(0), 1024)
. In questo caso, supponiamo che sia il file malloc(0)
sulla sinistra e sulla destra restituisce non-NULL
. Quindi, sono garantiti per essere diversi. Inoltre, il valore restituito da malloc()
sul lato sinistro non è stato free()
d ancora, quindi qualsiasi altro malloc()
, calloc()
o realloc()
potrebbe non restituire quel valore. Ciò significa che se hai scritto la tua condizione come:
if (malloc(0) == realloc(malloc(0), 1024)
puts("possible");
non vedrai possible
sull'output (a meno che sia malloc()
e realloc()
fallisce e restituisce NULL
).
#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;
}
Su OS X, il mio codice non ha prodotto nulla quando l'ho eseguito. Su Linux, stampa possible, OK
.
malloc(0)
è Implementazione definita per quanto riguarda C99.
Da C99 [Sezione 7.20.3]
L'ordine e la contiguità dell'archiviazione allocata dalle chiamate successive alle funzioni calloc, malloc e realloc non sono specificate . Il puntatore restituito se l'allocazione ha successo è opportunamente allineato in modo che possa essere assegnato a un puntatore a qualsiasi tipo di oggetto e quindi utilizzato per accedere a tale oggetto o a un array di tali oggetti nello spazio allocato (fino a quando lo spazio non viene esplicitamente deallocato). La durata di un oggetto allocato si estende dall'allocazione fino alla deallocazione. Ciascuna di tali allocazioni produrrà un puntatore a un oggetto disgiunto da qualsiasi altro oggetto. Il puntatore restituito punta all'inizio (indirizzo di byte più basso) dello spazio allocato. Se non è possibile allocare lo spazio, viene restituito un puntatore nullo. Se la dimensione dello spazio richiesto è zero, il comportamento è definito dall'implementazione :viene restituito un puntatore nullo o il comportamento è come se la dimensione fosse un valore diverso da zero, tranne per il fatto che il puntatore restituito non deve essere utilizzato per accedere a un oggetto.
In C89, malloc(0) dipende dall'implementazione - non so se C99 lo abbia risolto o meno. In C++, usando:
char * p = new char[0];
è ben definito:ottieni un puntatore valido, non nullo. Naturalmente, non puoi utilizzare il puntatore per accedere a ciò a cui punta senza invocare un comportamento indefinito.
Per quanto riguarda il motivo per cui esiste, è conveniente per alcuni algoritmi e significa che non è necessario sporcare il codice con test per valori zero.