2010-02-02 21 views
25
struct foo 
{ 
    int a; 
    int b; 
}; 

void* p = (void*)malloc(sizeof(struct foo)); 
((foo*)p)->a;//do something. 
free(p);//Is this safe? 
+1

È valido anche C? Non dovrebbe essere sizeof (struct foo)?:) –

+2

Non solo va bene il valore '' free '('' void * ', per definizione, tutto' free '()' mai vede è un 'void *', quindi tecnicamente, tutto ciò che viene liberato in C è 'void * ':-) –

+0

@Daniel - Se mi chiedi, dovrebbe essere' struct foo * p = malloc (sizeof * p)); 'ma che ne so? –

risposta

31

Sì.

malloc ritorna void * e libera prende void *, così alcuni dei vostri calchi sono prive di significato, e si sta sempre liberando un void * anche se si sta iniziando con qualche altro tipo di puntatore.

1

sì, è sicuro.

5

Sì - free prende un puntatore a vuoto, quindi quando lo si chiama, il puntatore viene (implicitamente) lanciato su un puntatore per annullare in ogni caso.

Il resto del codice non è così sicuro:

void* p = (void*)malloc(sizeof(foo)); 

Si dovrebbe non gettato il ritorno da malloc (in C). Questo può coprire l'errore di dimenticare #include <stdlib.h>

3

Sì. Il prototipo di funzione per free è ancora:

void free(void *ptr); 
13

Sì, è sicuro. Quando si assegna memoria, la libreria runtime tiene traccia delle dimensioni di ciascuna allocazione. Quando chiami free(), cerca l'indirizzo e, se trova un'assegnazione per quell'indirizzo, viene liberata la quantità corretta di memoria (il blocco che è stato assegnato a quell'indirizzo).

2

Forse non è sicuro a causa della magia che accade dietro le quinte. Il runtime C e/o il sistema operativo stesso monitorano attivamente la memoria restituita da malloc, incluse le dimensioni e la posizione. Vedi anche se ti sembra di passare un puntatore senza nome a free(), in effetti stai rimandando un riferimento a un oggetto che il gestore della memoria sta attivamente monitorando.

3

in C è perfettamente sicuro perché non ci sono distruttori da chiamare.

il sistema di memoria tiene traccia della loro dimensione di allocazioni.

in C++ è necessario eliminare lo stesso tipo di nuovo, compreso l'utilizzo dell'operatore delete [] per eliminare gli array new'ed.

questo è solo per assicurarsi che vengano chiamati i distruttori.

0

Sì, ma normalmente è un segno di design scadente. malloc() viene in genere utilizzato per allocare i buffer (array di grandi dimensioni dello stesso tipo primitivo) o oggetti (le strutture con i campi inizializzati). In entrambi i casi, il malloc e la connessione deve corrispondere così

unsigned char *rgba_buffer = malloc(width * hieght * 4); 
    /* use the buffer here */ 
    free(rgba_buffer); 

    BITSTREAM *bs = bitstream("bitfile.boin"); 
    /* use the bitstream here */ 
    destroy_bitstream(bs); 

    typedef struct 
    { 
    FILE *fp; 
    unsigned char ch; 
    int index; 
    } BITSTREAM; 


    BITSTREAM *bitstream(const char *filename) 
    { 
     BITSTREAM *bs = malloc(sizeof(BITSTREAM)); 
     bs->fp = fopen(filename "rb"); 
     /* etc */ 
     return bs; 
    } 

    void destroybitstream(BITSTREAM *bs) 
    { 
    if(bs) 
    { 
     if(bs->fp) 
      fclose(bs->fp); 
     free(bs); 
    } 
    } 

In un caso, malloc e abbinare libera, nell'altra viene restituita la memoria allocata, ci sono anche risorse secondarie, e la partita costruttore e distruttore. Dovrebbe essere raro allocare una regione di memoria, ma non sapere a cosa serve. E non dovresti essere interleaving assegnazioni e libera caoticamente.

Il moderno C++ stringe tutto ciò con puntatori unici che "possiedono" l'oggetto. Mentre si può avere un puntatore unico a vuoto, sarebbe molto raro.