Imposible liberar punteros const en C

¿Cómo puedo liberar un const char* ? Asigné memoria nueva utilizando malloc , y cuando bash liberarlo siempre recibo el error “tipo de puntero incompatible”

El código que causa esto es algo así como:

 char* name="Arnold"; const char* str=(const char*)malloc(strlen(name)+1); free(str); // error here 

Varias personas han publicado la respuesta correcta, pero siguen eliminándola por alguna razón. Necesitas lanzarlo a un puntero que no sea const; free toma un void* , no un const void* :

 free((char*)str); 

Tu código está invertido

Esta:

 char* name="Arnold"; const char* str=(const char*)malloc(strlen(name)+1); 

Debería verse así:

 const char* name="Arnold"; char* str=(char*)malloc(strlen(name)+1); 

El tipo de almacenamiento const le dice al comstackdor que no tiene la intención de modificar un bloque de memoria una vez asignado (dinámicamente o estáticamente). La liberación de la memoria lo está modificando. Tenga en cuenta que no necesita lanzar el valor de retorno de malloc () , pero eso es solo un lado.

Hay poco uso en la asignación dinámica de la memoria (que está haciendo, en función de la longitud del name ) y decirle al comstackdor que no tiene intención de usarla. Tenga en cuenta que usa el significado para escribirle algo y luego (opcionalmente) liberarlo más tarde.

Lanzar a un tipo de almacenamiento diferente no soluciona el hecho de que haya invertido los tipos de almacenamiento para comenzar 🙂 Simplemente hace que una advertencia desaparezca, lo que intentaba decirle algo.

Si el código se invierte (como debería ser), free() funcionará como se esperaba, ya que puede modificar la memoria que asignó.

No tiene sentido malloc un puntero a const, ya que no podrás modificar su contenido (sin feos hacks).

Sin embargo, FWIW, gcc acaba de dar una advertencia para lo siguiente:

 // // const.c // #include  #include  int main(void) { const char *p = malloc(100); free(p); return 0; } $ gcc -Wall const.c -o const const.c: In function 'main': const.c:8: warning: passing argument 1 of 'free' discards qualifiers from pointer target type $ 

Qué comstackdor estas usando ?

No hay propósito en lanzar un puntero malloc’d a const. Cualquier función que toma un puntero de const no debe ser responsable de liberar la memoria que se le pasó.

Hay casos en los que desea liberar un const* . Sin embargo, no desea hacerlo a menos que lo asigne / asigne en la misma función. De lo contrario, es probable que rompas las cosas. Vea el siguiente código para un ejemplo del mundo real. Uso const en las declaraciones de funciones para mostrar que no estoy cambiando el contenido de los argumentos. Sin embargo, se reasigna con un duplicado en minúscula (strdup) que debe liberarse.

 char* tolowerstring(const char *to_lower) { char* workstring = strdup(to_lower); for(;workstring != '\0'; workstring++) *workstring = tolower(workstring); return workstring; } int extension_checker(const char* extension, const char* to_check) { char* tail = tolowerstring(to_check); extension = tolowerstring(extension); while ( (tail = strstr( tail+1, extension)) ) { /* The +1 prevents infinite loop on multiple matches */ if ( (*extension != '.' ) && ( tail[-1] != '.')) continue; if ( tail[strlen(extension)] == '\0') { free(tail); free( (char*) extension); return 1; } } free(tail); free( (char *) extension); return 0; } 

Podría estar equivocado, pero creo que el problema radica en const . Lanza el puntero a no const como:

 free((char *) p); 

Porque const usted dice: No cambie los datos a los que apunta este puntero .

Varias respuestas han sugerido simplemente enviar a char* . Pero como el.pescado escribió arriba,

fundir const para no const es un síntoma de código de olor.

Hay advertencias de comstackción que protegen contra esto, como -Wcast-qual en gcc, que me parece muy útil. Si realmente tiene un caso válido para liberar un puntero const (a diferencia de lo que muchos han escrito aquí, hay casos válidos, como lo señala nlstd), podría definir una macro para este fin de esta manera:

 #define free_const(x) free((void*)(long)(x)) 

Esto funciona al menos para gcc. El doble reparto hace que la lógica -Wcast-qual no detecte esto como “casting const away”. No hace falta decir que esta macro debe usarse con cuidado. En realidad, solo se debe usar para punteros asignados en la misma función.

No puedes liberar const char * porque es const . Guarde los punteros recibidos de malloc en variables de puntero no const, para que pueda pasarlos a free . Puede pasar argumentos char * a funciones que toman argumentos const char * pero lo contrario no siempre es cierto.

 void foo (const char *x); char *ptr = malloc (...); foo (ptr); free (ptr); 

Si está hablando de C pura y tiene el control completo de la asignación de memoria, puede usar el siguiente truco para convertir (const char *) en (char *) que no le dará ninguna advertencia en el comstackdor:

 const char *const_str = (const char *)malloc(...); char *str = NULL; union { char *mutable_field_p; const char *const_field_p; } u; u.const_field_p = const_str; str = u.mutable_field_p; 

Ahora puedes usar free (str); para liberar la memoria.

Pero TENGA CUIDADO de que esto es malvado más allá de las palabras y solo debe usarse en un entorno estrictamente controlado (por ejemplo, una biblioteca que asigna y libera cadenas, pero no quiere permitir que el usuario las modifique). De lo contrario, terminará con su progtwig bloqueado cuando alguien proporciona Tiempo de comstackción “STRING” para su función gratuita.

Si echas un vistazo a la firma de la función libre, free siempre toma void * ptr como argumento, por lo tanto, debes convertirlo al tipo apropiado, es decir, libre ((void *) str); free no permite que los punteros const sean desasignados directamente, por lo tanto, debe convertirlo en un tipo no const

Creo que la verdadera respuesta es que free debe tomar un argumento const pointer y NULL debe definirse como un puntero const . Esto parece ser un error en los estándares. La liberación de un puntero const debe implementarse de la siguiente manera:

 free(p); p = NULL; 

No veo cómo un comstackdor podría generar código incorrecto en este caso, el const pointer p ya no es accesible, por lo que no importa si el objeto al que apunta es const , valid, else else. Su const así que no puede haber copias sucias en registros o en cualquier otro lugar. Es válido establecer un puntero const a otro valor, y el hecho de que ese valor sea NULL no importa porque el valor anterior ya no es accesible.

Creo que incluso si lanzas el puntero a un no-const, el resultado del libre albedrío depende de la implementación. ¡Normalmente const fue diseñado para variables que no quieres modificar!