Tengo este mensaje:pregunta C: eliminar la referencia única en un puntero de indirección doble ** vacío
expected 'void **' but argument is of type 'char **'
cuando traté de compilar algo similar a esto:
void myfree(void **v)
{
if(!v || !*v)
return;
free(*v);
*v = NULL;
return;
}
encontré lo que creo que es una solución después de leer esta pregunta en el desbordamiento de la pila:
Avoid incompatible pointer warning when dealing with double-indirection - Stack Overflow
Así ajusté a algo como esto:
#include <stdio.h>
#include <stdlib.h>
void myfree(void *x)
{
void **v = x;
if(!v || !*v)
return;
free(*v);
*v = NULL;
return;
}
int main(int argc, char *argv[])
{
char *test;
if((test = malloc(1)))
{
printf("before: %p\n", test);
myfree(&test);
printf("after: %p\n", test);
}
return 0;
}
¿Es esta C legal? Estoy desreferenciando un puntero de vacío, ¿no?
Gracias chicos
EDITAR 12/10/2010 16:45 EST:
Como se ha señalado free(NULL)
es seguro y regulado por la Norma C. Además, como se explica a continuación, mi ejemplo anterior no es legal C. Consulte la respuesta de caf, la respuesta de Zack y mi propia respuesta.
Por lo tanto, va a ser más fácil para mí para inicializar cualquier punteros a-ser-malloc'd como nulo y más tarde a poco libre() y nulos a cabo directamente en el código:
free(pointer);
pointer = NULL;
El razón por la que estaba buscando NULL en myfree() como lo hice fue por mis experiencias con fclose(). fclose(NULL)
puede segfault dependiendo de la plataforma (por ejemplo, xpsp3 msvcrt.dll 7.0.2600.5512) y entonces asumí (erróneamente) que lo mismo podría pasar con free(). Había pensado en lugar de complicar mi código con sentencias if que podría implementar mejor en una función.
Gracias a todos por la buena discusión
Algunos me llame a un pagano, pero me acaba de usar 'definir MyFree (x) {hacer libre (x); x = NULL} mientras (0) ' –
No está desreferenciando un 'puntero a vacío'. Está desreferenciando un 'puntero a puntero para anular', lo cual es perfectamente legal. – aschepler
En realidad, quiero corregir mi macro anterior: '#define myfree (x) do {void ** tmp_ = & x; libre (* tmp_); * tmp_ = NULL; } while (0) '(¡Pensé que no había forma de evitar la doble evaluación de' x' pero sí!) –