cosa malloc(0) return?[duplica]
Domanda
A questa domanda ha già una risposta qui:
- qual è il punto in malloc(0)? 17 risposte
Cosa malloc(0)
restituisce?La risposta sarebbe essere lo stesso per realloc(malloc(0),0)
?
#include<stdio.h>
#include<malloc.h>
int main()
{
printf("%p\n", malloc(0));
printf("%p\n", realloc(malloc(0), 0));
return 0;
}
Uscita dal gcc linux:
manav@manav-workstation:~$ gcc -Wall mal.c
manav@manav-workstation:~$ ./a.out
0x9363008
(nil)
manav@manav-workstation:~$
L'uscita continuano a cambiare ogni volta per malloc(0)
.Questa è una risposta standard?E perché qualcuno dovrebbe essere interessato a ottenere un puntatore, altri meno accademico e di ricerca?
EDIT:
Se malloc(0)
restituisce il manichino di puntatore, quindi come si fa a seguenti opere:
int main()
{
void *ptr = malloc(0);
printf("%p\n", realloc(ptr, 1024));
return 0;
}
EDIT:
Il codice seguente restituisce "possibile" per ogni iterazione.Perché non dovrebbe fallire ?
#include<stdio.h>
#include<malloc.h>
int main()
{
int i;
void *ptr;
printf("Testing using BRUTE FORCE\n");
for (i=0; i<65000; i++)
{
ptr = malloc(0);
if (ptr == realloc(ptr, 1024))
printf("Iteration %d: possible\n", i);
else
{
printf("Failed for iteration %d\n", i);
break;
}
}
return 0;
}
Soluzione
Altri hanno risposto come funziona malloc(0)
. Risponderò una delle domande che ha chiesto che non è stato ancora risposto (credo). La domanda riguarda realloc(malloc(0), 0)
:
Che cosa significa
malloc(0)
tornare? La risposta sarebbe uguale perrealloc(malloc(0),0)
?
Lo standard dice questo circa realloc(ptr, size)
:
- se
ptr
èNULL
, si comporta comemalloc(size)
, - altrimenti (
ptr
non èNULL
), esso dealloca il puntatore all'oggetto vecchio per daptr
e restituisce un puntatore in un buffer allocato. Ma sesize
è 0, C89 dice che l'effetto è equivalente afree(ptr)
. È interessante notare che, non riesco a trovare quella dichiarazione a C99 progetto (n1256 o n1336). Nel C89, l'unico valore sensato per tornare in quel caso sarebbeNULL
.
Quindi, ci sono due casi:
- rendimenti
malloc(0)
NULL
su un'implementazione. Poi la chiamatarealloc()
è equivalente arealloc(NULL, 0)
. Ciò equivale amalloc(0)
dall'alto (e cioèNULL
in questo caso). -
malloc(0)
ritorna nonNULL
. Poi, la chiamata è equivalente afree(malloc(0))
. In questo caso,malloc(0)
erealloc(malloc(0), 0)
sono non equivalente.
Si noti che non v'è un caso interessante qui: nel secondo caso, quando malloc(0)
ritorna non NULL
in caso di successo, può ancora tornare NULL
per indicare il fallimento. Questo si tradurrà in una chiamata, come:. realloc(NULL, 0)
, che sarebbe equivalente a malloc(0)
, che può o non può restituire NULL
Non sono sicuro se l'omissione di C99 è una svista o se ciò significa che nel C99, realloc(ptr, 0)
per non NULL
ptr
non equivale a free(ptr)
. Ho appena provato con gcc -std=c99
, e quanto sopra è equivalente a free(ptr)
.
Modifica : Credo di capire che cosa il vostro confusione è:
Diamo un'occhiata a un frammento dal codice di esempio:
ptr = malloc(0);
if (ptr == realloc(ptr, 1024))
È possibile che questo non è lo stesso di malloc(0) == realloc(malloc(0), 1024)
. Nel secondo, la chiamata malloc()
viene effettuata due volte, mentre nel primo, si sta passando un puntatore precedentemente assegnato a realloc()
.
Analizziamo il primo codice prima. Supponendo malloc(0)
non restituisce NULL
in caso di successo, ptr
ha un valore valido. Quando si esegue realloc(ptr, 1024)
, realloc()
fondamentalmente si dà un nuovo buffer che ha le dimensioni 1024 e il ptr
non è più valido. Un'implementazione conforme può restituire lo stesso indirizzo di quello già in ptr
. Così, la sua condizione if
può restituire vero. (Si noti, tuttavia, guardando il valore di ptr
dopo realloc(ptr, 1024)
possono essere undefined comportamento.)
Ora la domanda che si chiedono: malloc(0) == realloc(malloc(0), 1024)
. In questo caso, supponiamo che sia il malloc(0)
sulla LHS e RHS ritorna non NULL
. Poi, si sono garantiti per essere diverso. Inoltre, il valore restituito dal malloc()
sul lato sinistro non è stato ancora free()
d, in modo che qualsiasi altra malloc()
, calloc()
o realloc()
non può restituire tale valore. Questo significa che se hai scritto la sua condizione come:
if (malloc(0) == realloc(malloc(0), 1024)
puts("possible");
non si vedrà possible
sull'uscita (a meno che non sia malloc()
e realloc()
non riescono e NULL
ritorno).
#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 dato alcun output quando ho eseguito. Su Linux, stampa possible, OK
.
Altri suggerimenti
malloc(0)
è Attuazione Definiti per quanto C99 è interessato.
Da C99 [Sezione 7.20.3]
L'ordine e la contiguità di spazio di archiviazione allocato dalle chiamate successive alla calloc, malloc e realloc funzioni non è specificato.Il puntatore restituito se l'allocazione riesce opportunamente allineati in modo che possa essere assegnato ad un puntatore a qualsiasi tipo di oggetto e poi utilizzato per accedere ad un oggetto o un array di oggetti nello spazio destinato (fino a quando lo spazio è esplicitamente deallocato).Il ciclo di vita di un oggetto allocato si estende per l'assegnazione fino a quando la deallocazione.Ciascuno di tali quote sono resa un puntatore a un oggetto disgiunto da qualsiasi altro oggetto.Il puntatore restituito punti all'inizio (byte più basso indirizzo di spazio allocato.Se lo spazio non possono essere assegnati, un puntatore è null restituiti. Se la dimensione dello spazio richiesto è pari a zero, il comportamento di attuazione- definito:uno viene restituito un puntatore null, o il comportamento, è come se le dimensioni erano alcuni valore diverso da zero, tranne che il puntatore restituito non deve essere utilizzato per accedere a un oggetto.
In C89, malloc (0) è a carico di attuazione - non so se C99 ha fissato questo o no. In C ++, utilizzando:
char * p = new char[0];
è ben definito - si ottiene un, puntatore non nullo valida. Naturalmente, non è possibile utilizzare il puntatore per accedere a ciò a cui punta senza invocare un comportamento indefinito.
Per quanto riguarda il motivo per cui questo esiste, è conveniente per alcuni algoritmi, e significa che non c'è bisogno di lettiera il codice con i test per i valori zero.
standard di C99
Se lo spazio non può essere assegnato, un nullpointer viene restituito. Se le dimensioni dello spazio richiesto è pari a zero, il comportamento dipende dall'implementazione: sia un puntatore nullo viene restituito, o il comportamento è come se fosse la dimensione qualche valore diverso da zero, tranne che il puntatore restituito non deve essere utilizzato per accedere a un oggetto.
Il comp.lang.c FAQ ha la seguente dire:
L'ANSI / ISO standard dice che essa può effettuare una; il comportamento è implementazione definita (vedere la domanda 11.33). codice portabile deve o fare attenzione a non chiamare malloc (0), o essere preparato per la possibilità di un nullo tornare.
Quindi, probabilmente è meglio evitare di usare malloc(0)
.
Vedere C99, la sezione 7.20.3:
Se la dimensione dello spazio richiesto è zero, il comportamento è implementationdefined: o un nullo puntatore viene restituito, o il comportamento è come se la dimensione era un po 'diverso da zero valore, salvo che la tornata puntatore non deve essere utilizzato per accedere a un oggetto.
Questo è valido per tutte le tre funzioni di allocazione (cioè calloc()
, malloc()
e realloc()
).
Un punto a nessuno importava di parlare ancora, nel vostro primo programma è che realloc
con la lunghezza 0 è la stessa cosa di free
.
dalla pagina man di Solaris:
La funzione
realloc()
modifica la dimensione del blocco puntato a daptr
asize
byte e restituisce un puntatore al blocco (eventualmente spostato). I contenuti saranno invariate fino alla minore dei vecchi e nuovi formati. Septr
èNULL
,realloc()
si comporta comemalloc()
per la dimensione specificata. Sesize
è0
eptr
non è un puntatore nullo, lo spazio indicò viene fatta disponibile per ulteriori allocazione dall'applicazione, però non restituiti al sistema. La memoria è restituito al sistema solo al momento della cessazione dell'applicazione.
Se non si sa che può essere una fonte di brutta sorpresa (mi è successo).
Penso che dipenda. Ho controllato le fonti di Visual Studio 2005 e ho visto questo nella funzione _heap_alloc:
if (size == 0)
size = 1;
Credo che in molti casi può essere utile un puntatore valido, anche quando chiedono zero byte. Questo è perché questo comportamento coerente rende più facile per controllare i puntatori perché: se si dispone di un puntatore non-NULL è OK; se si dispone di un puntatore NULL probabilmente avete un problema. Ecco perché penso che la maggior parte delle implementazioni ritorneranno un puntatore valido, anche quando chiedono zero byte.
Se malloc (0) restituisce puntatore fittizia, allora come si fa in seguito a lavori:
void *ptr = malloc(0);
printf("%p\n", realloc(ptr, 1024));
Non so cosa si intende per "puntatore fittizio". Se malloc(0)
restituisce non NULL, quindi ptr
è un puntatore valido per un blocco di memoria di dimensioni pari a zero. L'implementazione malloc
salva queste informazioni in un modo specifico dell'implementazione. realloc
conosce la strada (attuazione specifiche) per capire che i punti ptr
ad un blocco di memoria di dimensioni pari a zero.
(Come malloc
/ realloc
/ free
farlo è specifico dell'implementazione. Una possibilità è quella di allocare 4 byte più richiesto e memorizzare la dimensione poco prima del blocco di memoria. In tal caso, ((int *)ptr)[-1]
darebbe la dimensione del blocco di memoria, che è 0
. non si dovrebbe mai fare questo dal codice, è solo per l'uso da realloc
e free
).