2008-09-25 15 views

Respuesta

30

Aquí está el capítulo y el versículo.

Si el argumento [de la función free] no coincide con un puntero anteriormente devuelto por la función calloc, malloc, o realloc, o si el espacio se ha desasignado por una llamada a free o realloc, la el comportamiento no está definido (ISO 9899:1999 - Programming languages — C, Sección 7.20.3.2)

+6

FYI: Cuando C o C++ dicen "indefinido", generalmente significan "bloqueo" o "corrupción de memoria" o algo igualmente terrible. Tener cuidado. –

+12

No, realmente significan "indefinido". Eso simplemente incluye bloqueos y corrupción de memoria. –

+5

@OrionEdwards El compilador podría, por ejemplo, decidir lanzar NetHack. – kyrias

14

Sí, puede obtener un doble error libre que hace que su programa falle. Tiene que ver con las estructuras internas de datos de malloc para hacer un seguimiento de la memoria asignada.

4

Dependiendo del sistema en el que lo ejecute, nada sucederá, el programa fallará, la memoria se dañará o cualquier otra cantidad de efectos interesantes.

2

No hagas eso. Si la memoria que se liberó se vuelve a asignar a otra cosa entre las llamadas al free, entonces las cosas se desordenarán.

+2

Por lo general, las cosas se arruinan incluso si la memoria no se reasigna entre las dos llamadas para liberar. –

18

Uno de nada, falta de memoria silenciosa o falla de segmentación.

+0

hrm, ¿de dónde sacaste esto? obtengo errores libres dobles ... –

+0

Segfaults ocurre cuando accede a la memoria que está fuera de los límites. – Mahouk

6

No es tan inteligente. Google para vulnerabilidades gratuitas dobles. Establezca su puntero a NULL después de la liberación para evitar dichos errores.

+0

Desafortunadamente, no puede escribir un contenedor para liberar que lo hace por usted, el puntero se pasa por valor, no como referencia. es decir, libre (vacío ** p) {libre (* p); * p = NULL;} Esto no es tan fácil de rediseñar el código con. – jbleners

+0

ajbl, usa una macro. #define freep (x) (free (x); x = 0;) –

+0

Mala idea, ya que no es aplicable a los valores de const. Usas valores const cuando sea posible, ¿verdad? –

3

Establezca siempre un puntero a NULL después de liberarlo. Es seguro intentar liberar un puntero nulo.

Vale la pena escribir su propio contenedor para hacerlo automáticamente.

+0

Su contenedor libre() debe ser una macro o debe usar una interfaz diferente de la función estándar free(). –

+0

Tenga en cuenta que la creación de dicho envoltorio no siempre es fácil ... – YoYoYonnY

2

Bad Things (TM)

En realidad, creo que es indefinido por lo que nada en absoluto incluyendo jugar "Guerra Mundial termonuclear" con la unidad central de NORAD

1

Se puede bloquearse su programa, corromper la memoria, o tienen otros efectos negativos más sutiles. Después de eliminar la memoria, es una buena idea configurarla en NULL (0). Intentar liberar un puntero nulo no hace nada, y está garantizado que es seguro. Lo mismo vale para delete en C++.

8

Resumen Respuesta:

Sí, las cosas malas puede y probablemente va a suceder.

Para evitar esta DO:

free(myString); 
myString = NULL; 

Tenga en cuenta que todas las referencias a la memoria se deben establecer en NULL si se crearan otros.

Además, si llama al free() con NULL, no se realizará ninguna acción. Para obtener más información, consulte: man free

+0

Tenga en cuenta que si ha hecho alguna copia del puntero, también debería establecerse en NULL. –

+0

Agregó una edición para dirigir su comentario. – lillq

+0

Parece que la comunidad se inclina más a poner resúmenes de respuestas en la pregunta real, no como una pregunta que aún está enterrada ... – PhirePhly

1

En resumen: "Comportamiento indefinido".

(Ahora, lo que eso puede incluir y por qué ese es el caso que los otros ya han dicho. Solo pensé que valía la pena mencionar aquí el término, ya que es bastante común).

+0

Google para 'demonios nasales' para obtener más información. –

1

La verdad es extraño macro a continuación es una drop-in útil de sustitución de la extinción de algunas clases de vulnerabilidades de seguridad, así como la depuración de ayuda desde accesos para liberar() 'd son regiones más probabilidades de segfault en lugar de corromper silenciosamente la memoria.

#define my_free(x) do { free(x); x = NULL; } while (0) 

El ciclo do-while es para ayudar a que el código circundante digiera más fácilmente los enunciados múltiples. p.ej. if (hecho) my_free (x);

+0

¿No funcionaría "#define my_free (x) {free (x); x = NULL;}" igual de bien? –

+0

No, después de la expansión hay un punto y coma ilegal en if (hecho) {free (x); x = NULL}; else do_more(); Buena suerte para encontrar el error "else without matching if" en su fuente original. – MSalters

+0

C tiene el operador de coma por un motivo.'#define my_free (x) (free ((x)), (x) = 0)' –

-1

Otra situación interesante:

char * myString = malloc(sizeof(char)*STRING_BUFFER_SIZE); 
char * yourString = myString; 

if (myString) 
{ 
    free(myString); 
    myString = NULL; 
} 
// Now this one is safe, because we keep to the rule for 
// setting pointers to NULL after deletion ... 
if (myString) 
{ 
    free(myString); 
    myString = NULL; 
} 

// But what about this one: 
if (yourString) 
{ 
    free(yourString); 
    yourString = NULL; 
} 

//?!? :) 
Cuestiones relacionadas