c pointers free compiler-optimization standards-compliance

¿Se permite al compilador reciclar variables de puntero liberado?



pointers free (1)

Se ha afirmado que

un compilador es libre de reutilizar la variable del puntero para algún otro propósito después el realloc ser liberado , por lo que no tiene garantía de que tenga el mismo valor que tenía antes

es decir

void *p = malloc(42); uintptr_t address = (uintptr_t)p; free(p); // [...] stuff unrelated to p or address assert((uintptr_t)p == address);

puede fallar.

C11 anexo J.2 lecturas

Se utiliza el valor de un puntero que se refiere al espacio desasignado por una llamada a la función libre o realloc (7.22.3) [ no está definido ]

pero el anexo, por supuesto, no es normativo.

El Anexo L.3 (que es normativo, pero opcional) nos dice que si

Se utiliza el valor de un puntero que se refiere al espacio desasignado por una llamada a la función libre o realloc (7.22.3).

Se permite que el resultado sea un comportamiento crítico indefinido.

Esto confirma el reclamo, pero me gustaría ver una cita apropiada del estándar en lugar del anexo.


Cuando un objeto llega al final de su vida útil, todos los punteros se vuelven indeterminados . Esto se aplica a las variables de ámbito de bloque y a la memoria mal asignada de la misma manera. La cláusula aplicable es, en C11, 6.2.4: 2.

La vida útil de un objeto es la parte de la ejecución del programa durante la cual se garantiza que el almacenamiento estará reservado para él. Existe un objeto, tiene una dirección constante y conserva su último valor almacenado durante toda su vida útil. Si se hace referencia a un objeto fuera de su vida útil, el comportamiento es indefinido. El valor de un puntero se vuelve indeterminado cuando el objeto al que apunta (o simplemente pasado) llega al final de su vida útil.

El uso de memoria indeterminada para cualquier cosa, incluida la comparación aparentemente inofensiva o la aritmética, es un comportamiento indefinido (en C90; los estándares posteriores complican el asunto terriblemente, pero los compiladores continúan tratando el uso de la memoria indeterminada como un comportamiento indefinido).

Como ejemplo, ¿qué tal el siguiente programa de impresión de que q son diferentes y iguales? Los resultados de la ejecución con varios compiladores se muestran here .

#include <stdlib.h> #include <stdio.h> #include <stdint.h> #include <inttypes.h> int main(int argc, char *argv[]) { char *p, *q; uintptr_t pv, qv; { char a = 3; p = &a; pv = (uintptr_t)p; } { char b = 4; q = &b; qv = (uintptr_t)q; } printf("Roses are red,/nViolets are blue,/n"); if (p == q) printf ("This poem is lame,/nIt doesn''t even rhyme./n"); else { printf("%p is different from %p/n", (void*)p, (void*)q); printf("%"PRIxPTR" is not the same as %"PRIxPTR"/n", pv, qv); } }