Pourquoi / pourquoi utiliser char * au lieu de const car * dans le type de retour peut provoquer des plantages?

StackOverflow https://stackoverflow.com/questions/1421672

  •  07-07-2019
  •  | 
  •  

Question

J'ai lu quelque part que si vous voulez qu'une fonction C / C ++ renvoie un tableau de caractères (par opposition à std :: string), vous devez renvoyer const char * plutôt que char *. Faire ce dernier peut provoquer le blocage du programme.

Quelqu'un pourrait-il expliquer si cela est vrai ou non? Si c'est vrai, pourquoi retourner un caractère * d'une fonction si dangereux? Merci.

const char * my_function()
{
    ....
}

void main(void)
{
    char x[] = my_function();
}
Était-ce utile?

La solution

Si vous avez une fonction qui renvoie "" littéraux de chaîne" " alors il doit retourner const char *. Ces derniers n'ont pas besoin d'être alloués sur le tas par malloc car ils sont compilés dans une section en lecture seule de l'exécutable lui-même.

Exemple:

const char* errstr(int err)
{
    switch(err) {
        case 1: return "error 1";
        case 2: return "error 2";
        case 3: return "error 3";
        case 255: return "error 255 to make this sparse so people don't ask me why I didn't use an array of const char*";
        default: return "unknown error";
    }
}

Autres conseils

Ce que l'on vous a dit n'est pas vrai.

Le renvoi d'un const char * peut améliorer la sémantique d'une fonction (ne modifiez pas ce que je vous donne), mais renvoyer un char * est parfaitement correct. bien.

Toutefois, dans les deux cas, vous devez vous assurer de renvoyer un char * ou un const char * qui a été alloué sur le tas dans ma_fonction (c'est-à-dire alloué avec malloc ou nouveau ), sinon chaque fois que ma_fonction est renvoyé , la mémoire du [const] char * sera désallouée et vous accéderez à un pointeur non valide.

Enfin, vous devez vous rappeler de libérer ou supprimer le [const] char * qui vous a été renvoyé une fois que vous avez terminé, sinon vous perdrez de la mémoire. Le C / C ++ n’est-il pas de si bons langages?

Donc, en C, vous auriez

const char *my_function() {
    const char *my_str = (const char *)malloc(MY_STR_LEN + 1);  // +1 for null terminator.
    /* ... */
    return my_str;
}

int main() {
    const char *my_str = my_function();
    /* ... */
    free(my_str);
    /* ... */
    return 0;
}

Généralement, ce n'est pas un problème, mais il y a des points à considérer. C'est généralement une question de const-correct, ce qui signifie de garder une trace de ce que vous pouvez changer et de ce que vous ne pouvez pas.

Si vous renvoyez une chaîne entre guillemets doubles, il s’agit de const char * , et le traiter comme tout le reste est une invitation au dérangement. Changer une telle chaîne est un comportement indéfini, mais provoque généralement un blocage du programme ou la modification de cette chaîne, quelle que soit sa référence.

Si vous renvoyez un tableau de caractères sur la pile (c'est-à-dire une variable locale d'une fonction appelée), il disparaîtra et le pointeur ne pointera sur rien en particulier, probablement avec des résultats erronés à un moment donné.

Si la fonction appelée renvoie quelque chose qui est déjà const char * , sa conversion en char * nécessite un transtypage. De plus, si vous voulez réellement le changer, vous devez être sûr que cela peut changer. Il est généralement préférable de le conserver sous la forme const char * .

La restitution de la mémoire allouée avec malloc () ou new ne pose pas de problème immédiat, mais vous avez le problème de la propriété: quelle fonction doit free () / supprimez-le , quand et que faites-vous des copies possibles? C’est là que brillent les pointeurs intelligents de C ++.

Si le caractère * est alloué sur la pile, vous retournez un pointeur suspendu. Autrement, tant que cela correspond au prototype de la fonction et que la déclaration correspond à la valeur de retour, tout va bien.

Changer simplement le code de retour ne provoquera pas de crash. Toutefois, si la chaîne que vous renvoyez est statique (par exemple, return "AString"), vous devez renvoyer const char * pour vous assurer que le compilateur détecte toute tentative de modification de celui-ci. mémoire, ce qui entraînera probablement un blocage. Vous pouvez certainement utiliser des conversions et autres pour contourner les vérifications du compilateur, mais dans ce cas, vous devez travailler pour que le crash se produise.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top