puntero constante calificador c const free

constante - No se pueden liberar los punteros const en C



const int c++ (12)

¿Cómo puedo liberar un const char* ? Asigné nueva memoria usando malloc , y cuando intento liberarla siempre recibo el error "tipo de puntero incompatible"

El código que causa esto es algo como:

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


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


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

free(p); p = NULL;

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


Hay casos en los que quieres liberar una const* . Sin embargo, no desea hacerlo a menos que lo asigne / asigne en la misma función. Si no, es probable que rompas cosas. Vea el código a continuación para ver 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úsculas (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; }


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


No puedes liberar const char * porque es const . Almacene los punteros recibidos de malloc en variables de puntero no constantes, 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);


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

Sin embargo, FWIW, gcc solo da una advertencia para lo siguiente:

// // const.c // #include <stdio.h> #include <stdlib.h> 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é compilador estas usando ?


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

free((char *) p);

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


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

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 malo más allá de las palabras y que solo debe usarse en un ambiente estrictamente controlado (por ejemplo, la biblioteca que asigna y libera cadenas, pero no quiere permitir que el usuario las modifique) De lo contrario, terminará con un programa que falla cuando alguien lo proporciona compile el tiempo "STRING" para su función libre.


Si observa la firma de la función gratuita, free siempre toma void * ptr como argumento, por lo tanto, debe convertirlo en el tipo apropiado, es decir, free ((void *) str); libre no permite que los punteros const sean desasignados directamente, por lo tanto, es necesario convertirlos en tipos no const


Su código se invierte.

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 compilador que no tiene la intención de modificar un bloque de memoria una vez asignada (de forma dinámica o estática). Liberar la memoria lo está modificando. Tenga en cuenta que no es necesario emitir el valor de retorno de malloc () , pero eso es solo un aparte.

Hay poco uso en la asignación dinámica de memoria (lo que está haciendo, según la longitud del name ) y en decirle al compilador que no tiene intención de usarla. Tenga en cuenta que usar significado significa escribir algo y luego (opcionalmente) liberarlo más tarde.

La conversión a un tipo de almacenamiento diferente no soluciona el hecho de que, para empezar, invirtió los tipos de almacenamiento :) Simplemente hace que desaparezca una advertencia que intentaba decirle algo.

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


Varias personas han publicado la respuesta correcta, pero siguen eliminándola por alguna razón. Es necesario convertirlo en un puntero no constante; free toma un void* , no un const void* :

free((char*)str);


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

La conversión de const a non- const es un síntoma del olor del código.

Hay advertencias de compilació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 de const (al contrario de lo que muchos han escrito aquí, hay casos válidos, como lo señala nlstd), podría definir una macro para ese propósito como este:

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

Esto funciona al menos para gcc. El doble lanzamiento 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 utilizar para los punteros asignados en la misma función.