2010-02-02 38 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

¿Esto es válido incluso C? ¿No debería ser eso sizeof (struct foo)?:) –

+2

No solo está bien para 'free()' a 'void *' valor, por definición, todo 'free()' ever ve es un 'void *', así que, técnicamente, todo lo liberado en C es 'void * ':-) –

+0

@Daniel - Si me preguntas, debería ser' struct foo * p = malloc (sizeof * p)); 'pero ¿qué sé? –

Respuesta

31

Sí.

malloc regresa void * y libre toma void *, por lo que algunos de sus moldes no tienen sentido, y siempre estamos liberando una void * incluso si estás empezando con algún otro tipo de puntero.

5

Sí - free toma un puntero a vacío, por lo que cuando lo llamas, el puntero se convierte (implícitamente) en un puntero para anular en cualquier caso.

El resto de su código no es tan segura:

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

Usted debe no tire la vuelta de malloc (en C). Esto puede encubrir el error de olvidar a #include <stdlib.h>

3

Sí. El prototipo de función para free es par:

void free(void *ptr); 
13

Sí, es seguro. Al asignar memoria, la biblioteca de tiempo de ejecución realiza un seguimiento del tamaño de cada asignación. Cuando llama a free(), busca la dirección, y si encuentra una asignación para esa dirección, se libera la cantidad correcta de memoria (el bloque que se asignó a esa dirección).

2

Tal vez no siente seguro debido a la magia que ocurre detrás de las escenas. El tiempo de ejecución de C y/o el propio sistema operativo está realizando un seguimiento activo de la memoria devuelta por malloc, incluido su tamaño y ubicación. Aunque parece que está devolviendo un puntero sin letra a free(), de hecho, remite una referencia a un objeto que el administrador de memoria está rastreando activamente.

3

en C es perfectamente seguro porque no hay destructores para llamar.

el sistema de memoria realiza un seguimiento del tamaño de las asignaciones.

en C++ debe eliminar el mismo tipo que el nuevo, incluido el uso del operador delete [] para eliminar matrices nuevas.

esto es solo para asegurarse de que se invocan destructores.

0

Sí, pero normalmente es un signo de diseño deficiente. malloc() se utiliza normalmente para asignar almacenamientos intermedios (matrices grandes del mismo tipo primitivo) u objetos (estructuras con campos inicializados). En ambos casos, el malloc y la libre debe coincidir con lo que

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); 
    } 
    } 

En un caso, malloc y sin rapport, en la otra se devuelve la memoria asignada, también hay recursos secundarios, y el partido constructor y el destructor. Sería raro asignar una región de memoria, pero no saber para qué se usa. Y no debe intercalar asignaciones y libera caóticamente.

C++ moderno ajusta todo esto con punteros únicos que "poseen" el objeto. Aunque puede tener un puntero único para anular, sería muy raro.