2009-07-02 18 views
39

domanda molto semplice, ho fatto il seguente programma:a zero dimensioni malloc

#include <stdlib.h> 
int main(int argc, char ** argv) 
{ 
    void * ptr; 
    ptr = malloc(0); 
    free(ptr); 
} 

E non segfault sulla mia macchina. È un comportamento portatile di stdlib malloc e gratuito, o sto cercando problemi?

Modifica: Ciò che sembra non portabile è il valore restituito da malloc. La domanda riguarda la combinazione malloc (0) + libera, non il valore di ptr.

+1

Tenete a mente che, se questo non ha funzionato, non ci deve essere un sacco di special-case codice. Le persone effettueranno un malloc un numero di byte basato su una variabile o un'espressione per tutto il tempo, e sarebbe scomodo dover controllare lo zero ogni volta. –

+0

correlati: http://stackoverflow.com/questions/2022335/whats-the-point-in-malloc0 – jldupont

+0

Lo so: commento super tardivo su questa domanda chiusa. Ma c'è _sometimes_ un uso per 'malloc (0)' che non è menzionato. Su quelle implementazioni in cui restituisce un valore non NULL, specialmente in un build DEBUG, probabilmente alloca PIÙ di quello che hai richiesto e ti dà il puntatore appena oltre la sua intestazione interna. Ciò consente di ottenere un valore _ _ per l'effettivo utilizzo della memoria se si ottiene questo prima e dopo una serie di allocazioni. –

risposta

54

Il comportamento è definito dall'implementazione, riceverai un puntatore NULL o un indirizzo. Chiamare gratis per il puntatore ricevuto non dovrebbe tuttavia causare un problema dato:

  • gratuito (NULL) è ok, non vengono effettuate operazioni
  • gratuito (indirizzo) è ok, se l'indirizzo è stato ricevuto da malloc (o altri come calloc ecc.
23

È possibile restituire NULL e è consentito restituire un puntatore non NULL non è possibile effettuare il dereference. Entrambi i modi sono sanzionate dallo standard (7.20.3):

Se la dimensione dello spazio richiesto è nullo, il comportamento è implementazione definita: o un puntatore nullo viene restituito, o il comportamento è se la dimensione era un valore diverso da zero, ad eccezione del fatto che il puntatore restituito non deve essere utilizzato per accedere a un oggetto.

+1

Questa non è esattamente la domanda posta. Non mi interessa il valore restituito da malloc, ma sulla chiamata gratuita su un puntatore restituito da malloc (0). – shodanex

+2

È ancora un'ottima risposta perché, insieme alla risposta di Key, offre una panoramica completa del comportamento. – schnaader

3

scusiamo per il disturbo, ho dovuto leggere le pagine man:

malloc() alloca byte di dimensione e restituisce un puntatore alla memoria allocata. La memoria non è cancellata. Se la dimensione è 0, malloc() restituisce NULL o un valore di puntatore univoco che può essere successivamente passato correttamente a free().

libero() libera lo spazio di memoria indicato da ptr, che deve essere stato restituito da una precedente chiamata a malloc(), calloc() o realloc(). In caso contrario, o se libero (ptr) è già stato chiamato prima, si verifica un comportamento non definito. Se ptr è NULL, non viene eseguita alcuna operazione.

Sembra è vero almeno per il GNU libc

+4

RTFM :) http://en.wikipedia.org/wiki/RTFM –

1

aggiornati per tener conto LIBT & commenti di Pax:

Il comportamento di chiamare malloc (0) è a carico di attuazione o in altre parole non portabile e indefinito.

Link a CFaq domanda per maggiori dettagli.

+2

Gli standard ISO distingue chiaramente tra definito, definito dall'implementazione e non definito. Dovresti anche tu. Definito dall'implementazione significa che * è * definito ma il documento per quell'implementazione ti dirà cosa fa. Undefined significa che può fare * assolutamente qualsiasi cosa * inclusa, ma non solo, la distruzione totale dell'universo. – paxdiablo

+0

grazie per il chiarimento (e il voto negativo ;-)). Ho usato il termine "indefinito" piuttosto liberamente là. Colpa mia. –

+0

Hai frainteso il faq. non significa dire che il comportamento generale è definito dall'implementazione. Significa che il risultato è NULL o qualche altro valore è definito dall'implementazione. Ad esempio, il comportamento valido non include l'invio di un sigsegv. –

1

Secondo la norma c

7.20.3 Se la dimensione dello spazio richiesto è nullo, il comportamento è definito attuazione: o un puntatore nullo viene restituito, o il comportamento è come se fosse una dimensione valore diverso da zero, tranne per il fatto che il puntatore restituito non deve essere utilizzato per accedere a un oggetto.

-2

Nella mia esperienza, ho visto che malloc (0) restituisce un puntatore che può essere liberato. Ma questo causa SIGSEGV nelle successive istruzioni di malloc(). E questo era altamente casuale.

Quando ho aggiunto un assegno, per non chiamare malloc se la dimensione da assegnare è zero, mi sono liberato di questo.

Quindi, vorrei suggerire di non allocare memoria per dimensione 0.

-Ashutosh