Renvoyer un pointeur sur une variable automatique

Disons que vous avez la fonction suivante:

char *getp() { char s[] = "hello"; return s; } 

Puisque la fonction renvoie un pointeur sur une variable locale dans la fonction à utiliser à l’extérieur, cela provoquera-t-il une fuite de mémoire?

PS je suis encore en train d’apprendre le C, alors ma question est peut-être un peu naïve …

[Mettre à jour]
Donc, si vous voulez retourner un nouveau tableau char[] (c’est-à-dire peut-être pour une fonction de sous-chaîne), que retournez-vous exactement? Devrait-il être un pointeur sur une variable externe? c’est-à-dire un caractère char[] qui n’est pas local à la fonction?

Cela ne causera pas de fuite de mémoire. Cela provoquera une référence en suspens. La variable locale est allouée sur la stack et sera libérée dès qu’elle sortira du domaine. Par conséquent, lorsque la fonction se termine, le pointeur que vous renvoyez ne pointe plus vers une mémoire que vous possédez. Ce n’est pas une fuite de mémoire (une fuite de mémoire survient lorsque vous allouez de la mémoire sans la libérer).

[Mise à jour] : Pour pouvoir retourner un tableau alloué dans une fonction, vous devez l’allouer en dehors de la stack (par exemple dans le tas) comme suit:

 char *test() { char* arr = malloc(100); arr[0] = 'M'; return arr; } 

Maintenant, si vous ne free pas la mémoire dans la fonction appelante une fois que vous avez fini de l’utiliser, vous aurez une fuite de mémoire.

Non, il ne coulera pas, car il est détruit après la fin de getp ();

Cela entraînera un comportement indéfini, car vous avez maintenant un pointeur sur une zone de mémoire qui ne contient plus ce que vous pensez, et qui peut être réutilisé par n’importe qui.

Une fuite de mémoire se produirait si vous stockiez ce tableau sur le tas, sans exécuter d’appel de free ().

 char* getp(){ char* p = malloc(N); //do stuff to p return p; } int main(){ char* p = getp(); //free(p) No leak if this line is uncommented return 0; } 

Ici, p n’est pas détruit car ce n’est pas dans la stack, mais dans le tas. Cependant, une fois le programme terminé, la mémoire allouée n’a pas été libérée, ce qui a provoqué une fuite de mémoire (même si cette opération est terminée une fois le processus terminé).

[METTRE À JOUR]

Si vous voulez renvoyer une nouvelle chaîne de caractères d’une fonction, vous avez deux options.

  • Stockez-le dans le tas (comme dans l’exemple ci-dessus ou comme cet exemple réel qui renvoie une chaîne dupliquée);
  • Passer un paramètre de tampon

par exemple:

  //doesnt exactly answer your update question, but probably a better idea. size_t foo (const char* str, size_t strleng, char* newstr); 

Ici, vous devrez allouer de la mémoire quelque part pour newstr (stack ou tas) avant d’appeler la fonction foo. Dans ce cas particulier, il renverrait le nombre de caractères dans newstr.

Ce n’est pas une fuite de mémoire car la mémoire est libérée correctement.

Mais c’est un bug. Vous avez un pointeur sur la mémoire non allouée . C’est ce qu’on appelle une référence en suspens et une source commune d’erreurs en C. Les résultats ne sont pas définis. Vous ne verrez aucun problème jusqu’au moment où vous essayez d’utiliser ce pointeur.

Les variables automatiques sont détruites à la fin de l’appel de fonction; vous ne pouvez pas leur renvoyer un pointeur. Ce que vous faites pourrait être décrit comme “renvoyant un pointeur sur le bloc de mémoire qui contenait autrefois s, mais qui est maintenant inutilisé (mais qui peut encore contenir quelque chose, du moins pour le moment) et qui sera rapidement rempli autrement entièrement. ”

Cela ne provoquera pas de fuite de mémoire, mais un comportement indéfini. Ce cas est particulièrement dangereux car le pointeur pointe quelque part dans la stack du programme et, si vous l’utilisez, vous accédez à des données aléatoires. Ce pointeur, lorsqu’il est écrit, peut également être utilisé pour compromettre la sécurité du programme et lui faire exécuter du code arbitraire.

Personne d’autre n’a encore mentionné une autre façon de rendre cette construction valide: dites au compilateur que vous voulez que le tableau “s” ait une “durée de stockage statique” variable). Vous faites cela avec le mot clé “static”:

 char *getp() { static char s[] = "hello"; return s; } 

Or, l’inconvénient est qu’il n’ya plus qu’une seule instance de s partagée entre chaque appel de la fonction getp (). Avec la fonction telle que vous l’avez écrite, cela n’aura aucune importance. Dans des cas plus complexes, il se peut que cela ne fasse pas ce que vous voulez.

PS: Le type habituel de variables locales a ce qu’on appelle “durée de stockage automatique”, ce qui signifie qu’une nouvelle instance de la variable est créée lors de l’appel de la fonction et disparaît à son retour. Il existe un mot clé “auto” correspondant, mais il est de toute façon implicite si vous n’utilisez pas “statique”, vous ne le verrez donc presque jamais dans le code du monde réel.

J’ai supprimé ma réponse précédente après avoir mis le code dans un débogueur et surveillé le désassemblage et la fenêtre de la mémoire.

Le code de la question n’est pas valide et renvoie une référence à la mémoire de stack, qui sera écrasée.

Cette version légèrement différente, cependant, renvoie une référence à la mémoire fixe et fonctionne correctement:

 char *getp() { char* s = "hello"; return s; } 

s est une variable de stack – elle est automatiquement dé-référencée à la fin de la fonction. Cependant, votre pointeur ne sera pas valide et fera référence à une zone de mémoire qui pourrait être écrasée à tout moment.