Impossible de libérer les pointeurs const dans C

Comment puis-je libérer un const char* ? J’ai alloué une nouvelle mémoire en utilisant malloc , et quand j’essaie de le libérer, je reçois toujours l’erreur “type de pointeur incompatible”

Le code qui provoque ceci est quelque chose comme:

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

    Plusieurs personnes ont affiché la bonne réponse, mais elles continuent à la supprimer pour une raison quelconque. Vous devez le convertir en un pointeur non-const; free prend un void* , pas un const void* :

     free((char*)str); 

    Votre code est inversé.

    Ce:

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

    Devrait ressembler à ceci:

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

    Le type de stockage const indique au compilateur que vous n’avez pas l’intention de modifier un bloc de mémoire une fois alloué (dynamicment ou statiquement). Libérer de la mémoire est en train de le modifier. Notez que vous n’avez pas besoin de lancer la valeur de retour de malloc () , mais ce n’est qu’une exception.

    Il est peu utile d’allouer dynamicment de la mémoire (que vous faites en fonction de la longueur du name ) et de dire au compilateur que vous n’avez pas l’intention de l’utiliser. Notez, en utilisant le sens, en y écrivant quelque chose, puis en le libérant (éventuellement) ultérieurement.

    Passer à un type de stockage différent ne résout pas le fait que vous avez inversé les types de stockage pour commencer 🙂 Cela déclenche simplement un avertissement, qui essayait de vous dire quelque chose.

    Si le code est inversé (comme il se doit), free() fonctionnera comme prévu car vous pouvez réellement modifier la mémoire que vous avez allouée.

    Cela n’a aucun sens de faire un pointeur sur const, vous ne pourrez pas modifier son contenu (sans hacks).

    FWIW cependant, gcc donne juste un avertissement pour les éléments suivants:

     // // 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 $ 

    Quel compilateur utilisez-vous ?

    Il n’y a aucune raison de convertir un pointeur malloc en const. Toute fonction qui prend un pointeur const ne devrait pas être responsable de la libération de la mémoire qui lui a été transmise.

    Il y a des cas où vous voulez libérer un const* . Cependant, vous ne voulez pas le faire, sauf si vous l’affectez / atsortingbuez la même fonction. Sinon, vous êtes susceptible de casser des choses. Voir le code ci-dessous pour un exemple du monde réel. J’utilise const dans les déclarations de fonction pour montrer que je ne modifie pas le contenu des arguments. Cependant, il est réaffecté avec une copie en minuscules (strdup) qui doit être libérée.

     char* tolowerssortingng(const char *to_lower) { char* workssortingng = strdup(to_lower); for(;workssortingng != '\0'; workssortingng++) *workssortingng = tolower(workssortingng); return workssortingng; } int extension_checker(const char* extension, const char* to_check) { char* tail = tolowerssortingng(to_check); extension = tolowerssortingng(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; } 

    Je peux me tromper mais je pense que le problème réside dans const . Convertissez le pointeur en non-const comme:

     free((char *) p); 

    Car avec const vous dites: ne changez pas les données pointées par ce pointeur .

    Plusieurs réponses suggèrent simplement de jeter à la char* . Mais comme el.pescado a écrit ci-dessus,

    La const de const en non- const est un symptôme d’une odeur de code.

    Il existe des avertissements du compilateur qui -Wcast-qual contre cela, tels que -Wcast-qual dans gcc, que je trouve très utile. Si vous avez vraiment un cas valide pour libérer un pointeur de const (contrairement à ce que beaucoup ont écrit ici, il existe des cas valides, comme indiqué par nlstd), vous pouvez définir une macro pour cela:

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

    Cela fonctionne au moins pour gcc. Le double cast fait que la logique -Wcast-qual ne le détecte pas comme “casting const away”. Inutile de dire que cette macro doit être utilisée avec précaution. En fait, il ne devrait être utilisé que pour les pointeurs affectés dans la même fonction.

    Vous ne pouvez pas libérer const char * car il est const . Stockez les pointeurs reçus de malloc dans des variables de pointeur non const, afin de pouvoir les transmettre free . Vous pouvez passer des arguments char * à des fonctions prenant des arguments const char * , mais le contraire n’est pas toujours vrai.

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

    Si vous parlez de C pur et que vous contrôlez totalement l’allocation de mémoire, vous pouvez utiliser l’astuce suivante pour lancer (const char *) vers (char *) qui ne vous avertira pas dans le compilateur:

     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; 

    Maintenant, vous pouvez utiliser gratuitement (str); pour libérer la mémoire.

    Mais attention, ceci est mal au-delà des mots et ne devrait être utilisé que dans un environnement ssortingctement contrôlé (par exemple, une bibliothèque qui alloue et libère des chaînes, mais ne veut pas autoriser les utilisateurs à les modifier). comstackr le temps “STRING” à votre fonction libre.

    Si vous examinez la signature de la fonction libre, free prend toujours comme argument vid * ptr, vous devez donc le convertir au type approprié, c’est-à-dire free ((void *) str); free ne permet pas de désallouer directement les pointeurs const, vous devez donc le convertir en un type non const

    Je pense que la vraie réponse est que free devrait prendre un argument de pointeur const et NULL devrait être défini comme un pointeur de const . Cela semble être un bug dans les normes. Libérer un pointeur const doit être implémenté comme suit:

     free(p); p = NULL; 

    Je ne vois pas comment un compilateur pourrait générer du code incorrect dans ce cas, le pointeur const p n’est plus accessible, donc peu importe si l’object indiqué est const , valide, etc. Sa const il n’y a donc pas de copies sales dans les registres ou ailleurs. Il est valide de définir un pointeur const sur une autre valeur et le fait que cette valeur soit NULL importe peu car la valeur précédente n’est plus accessible.

    Je pense que même si vous transformez le pointeur en non-const, le résultat du libre arbitre dépend de l’implémentation. Normalement, const a été conçu pour une variable que vous ne voulez pas modifier!