11
votes

Retourner un pointeur sur une variable automatique

dise que vous avez la fonction suivante: xxx

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

ps Je suis toujours en train d'apprendre que ma question peut donc être un peu naïf ...

[Mettre à jour]

Donc, si vous voulez que vous souhaitiez retourner un nouveau Char [] (c.-à-d. Peut-être pour une fonction de sous-chaîne), que revenez-vous exactement? Devrait-il être pointeur sur une variable externe? c'est-à-dire un char [] qui n'est pas local à la fonction?


0 commentaires

8 Réponses :


26
votes

Cela ne provoquera pas de fuite de mémoire. Ça va causer une référence pendante. La variable locale est allouée sur la pile et sera libérée dès qu'elle dépasse de la portée. En conséquence, lorsque la fonction se termine, le pointeur que vous retournez plus sur une mémoire que vous possédez. Ce n'est pas une fuite de mémoire (la fuite de mémoire est lorsque vous allouez de la mémoire et ne le libérez pas).

[mise à jour] : Pour pouvoir renvoyer une matrice allouée dans une fonction, vous devriez l'attribuer à l'extérieur de la pile (par exemple dans le tas) comme: xxx

maintenant, si vous ne GRATUIT La mémoire de la fonction d'appel après avoir fini de l'utiliser, vous aurez une fuite de mémoire.


2 commentaires

Est-ce que l'attribution arr [0] = 'm'; nécessaire ou était-il juste de démontrer une opération non-triviale sur Arr ?


@ user1717828 ce dernier.



13
votes

Non, cela ne va pas fuir, car sa chose détruite après la fin de GETP ();

Cela entraînera un comportement non défini, car vous avez maintenant un pointeur sur une zone de mémoire qui ne tient plus ce que vous pensez que ce que vous pensez. Peut être réutilisé par quiconque. P>

Une fuite de mémoire se produirait si vous stockiez ce tableau sur le tas, sans exécuter un appel à libérer (). P>

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


0 commentaires

8
votes

Ce n'est pas une fuite de mémoire car la mémoire est en cours de libération.

mais c'est un bug. vous avez un pointeur sur non alloué la mémoire . Il s'appelle un Référence dangereuse et est une source courante d'erreurs dans C. le Les résultats sont indéfinis. Vous ne verrez aucun problème jusqu'à ce que vous essayez d'utiliser ce pointeur.


0 commentaires

0
votes

s est une variable de pile - elle est automatiquement 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.


1 commentaires

Ce n'est pas désémarréé, mais n'est plus attribué à la pile.



2
votes

Cela ne causera pas de fuite de mémoire, mais cela entraînera un comportement indéfini. Cette affaire est particulièrement dangereuse car le pointeur pointera quelque part dans la pile du programme, et si vous l'utilisez, vous aurez accès à des données aléatoires. Un tel pointeur, lorsqu'il est écrit, peut également être utilisé pour compromettre la sécurité du programme et le faire exécuter du code arbitraire.


0 commentaires

3
votes

Les variables automatiques sont détruites à la fin de l'appel de la fonction; Vous ne pouvez pas retourner un pointeur pour eux. Ce que vous faites pourrait être décrit comme «retourner un pointeur sur le bloc de la mémoire qui contenait S, mais est maintenant inutilisé (mais pourrait encore avoir quelque chose, au moins pour le moment) et cela sera rapidement rempli de quelque chose sinon entièrement. "


0 commentaires

1
votes

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

Le code de la question est invalide et renvoie une référence à la mémoire de pile, qui sera écrasée. < / p>

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


0 commentaires

2
votes

Personne d'autre n'a encore mentionné une autre manière que vous pouvez effectuer cette construction valide: indiquez au compilateur que vous souhaitez que le tableau "s" ait "la durée de stockage statique" (cela signifie qu'il vit pour la vie du programme, comme une variable globale). Vous faites cela avec le mot-clé "statique": xxx

Maintenant, l'inconvénient de ceci est qu'il n'y a maintenant que une instance de S, partagée entre chaque invocation de la fonction getP (). Avec la fonction que vous l'avez écrite, cela n'aura pas d'importance. Dans des cas plus compliqués, cela pourrait ne pas faire ce que vous voulez.

PS: Le type habituel de variables locales a ce qu'on appelle "la durée de stockage automatique", ce qui signifie qu'une nouvelle instance de la variable est mise en existence Lorsque la fonction est appelée et disparaît lorsque la fonction revient. Il y a un mot-clé correspondant "Auto", mais il est impliqué de toute façon si vous n'utilisez pas "statique", vous ne le voyez presque jamais dans le code du monde réel.


2 commentaires

Les statiques sont-ils stockés sur le tas?


Non, ils sont chargés / créés au démarrage du programme, une mémoire pour eux est donc généralement attribuée de la même manière que la mémoire contient le texte du programme lui-même.