¿Se le permite al compilador reciclar variables de puntero liberadas?

4 minutos de lectura

Se ha afirmado que

un compilador es libre de reutilizar la variable de puntero para algún otro propósito después la reasignación siendo liberadopor 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 dice

Se utiliza el valor de un puntero que hace referencia al espacio desasignado por una llamada a la función free o realloc (7.22.3) [is undefined]

pero el anexo, por supuesto, no es normativo.

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

Se utiliza el valor de un puntero que hace referencia al espacio desasignado por una llamada a la función free 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 propiamente dicho en lugar del anexo.

  • Relacionado: stackoverflow.com/questions/17024866/…

    –Oliver Charlesworth

    27 de septiembre de 2014 a las 10:53

  • Dicho esto, no se sigue lógicamente que el compilador pueda “reutilizarlo”. Por supuesto, ese es un posible resultado de un comportamiento indefinido.

    –Oliver Charlesworth

    27/09/2014 a las 10:54


  • (uintptr_t)p provoca un comportamiento indefinido: no puede usar p‘s valor después de liberarlo. (Tiene el mismo estado que una variable no inicializada)

    –MM

    27 de septiembre de 2014 a las 11:08

  • @georgem: sí, aparentemente esto es UB; por lo que los punteros no son solo números enteros con azúcar, pueden invalidarse si pasado por valor a las funciones ‘mágicas’; personalmente creo que esto viola la POLA, pero es lo que es…

    – Cristóbal

    27/09/2014 a las 12:35


  • “no se sigue lógicamente que el compilador pueda “reutilizarlo”. — Lo hace si entiendes lo que significa la palabra “podría” y la lógica modal básica.

    –Jim Balter

    27/09/2014 a las 19:19

Cuando un objeto llega al final de su vida útil, todos los punteros hacia él se vuelven indeterminado. Esto se aplica a las variables de alcance de bloque y a la memoria mallocada 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 se le reservará almacenamiento. Un objeto existe, tiene una dirección constante y conserva su último valor almacenado durante su vida útil. Si se hace referencia a un objeto fuera de su vida útil, el comportamiento no está definido. 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 la memoria indeterminada para cualquier cosa, incluida la comparación o la aritmética aparentemente inofensiva, es un comportamiento indefinido (en C90; los estándares posteriores complican terriblemente el asunto, pero los compiladores continúan tratando el uso de la memoria indeterminada como un comportamiento indefinido).

Como ejemplo, ¿qué tal si el siguiente programa imprime eso? p y q son diferentes y lo mismo? Se muestran los resultados de la ejecución con varios compiladores. aquí.

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

  • si pudiera, te daría otro voto a favor blog.regehr.org/archives/1180 – aunque no estoy de acuerdo con todas las propuestas, es motivo de reflexión…

    – Cristóbal

    27/09/2014 a las 12:38

  • @Christoph Sería completamente en contra del espíritu de SO 🙂

    – Pascal Cuoq

    27 de septiembre de 2014 a las 13:04

  • @PascalCuoq: ¿Qué opinas de en.cppreference.com/w/c/language/analyzability ? Si la captura fuera opcional y se cambiara para permitir algunas operaciones de puntero actualmente ilegales, creo que debería ser bastante fácil de implementar para los compiladores [if they mostly ignore the trapping part].

    – Super gato

    28/04/2015 a las 21:54

  • @supercat Es interesante, pero la pelota está en la cancha de los implementadores del compilador.

    – Pascal Cuoq

    28/04/2015 a las 22:15

  • Esta: blog.regehr.org/archives/1180es una idea muy sensata, espero que esta idea se implemente en algún momento

    – Giorgi Moniava

    21 de febrero de 2016 a las 20:29


¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad