0
votes

Fuite de mémoire du manque de libre () dans cette fonction

Le code suivant est utilisé pour trouver le chemin d'un exécutable pour une coque rudimentaire dans C . Comme vous pouvez le constater, j'alloque de manière dynamique la variable PATH , puis vérifiez si le chemin existe (via lstat dans une fonction d'assistance cmd_exists ) . Je retourne ensuite la variable du chemin. Mon problème est que cela provoque une fuite de mémoire, car chemin n'est jamais libéré. Je ne peux pas me libérer de chemin avant de retourner sa valeur et, à ce moment-là, je ne peux penser à aucun moyen de libérer la mémoire qui a été allouée. Si quelqu'un peut m'aider, je l'apprécierais. Merci xxx


5 commentaires

Où est cette fonction utilisée? GRATUIT Il existe une fois que vous avez terminé. Comment créer un exemple minimal, complet et vérifiable


L'appelant doit libérer la mémoire, car il s'agit maintenant du propriétaire.


Mon problème est que cela provoque une fuite de mémoire, car le chemin n'est jamais libéré? Vous pouvez libérer le trajet après la fonction Find_Path () est appelé . Pour E.G Char * Temp = Find_Path (x, y); , puis gratuit (TEMP) Si l'utilisation avec TEMP est terminée.


Demandez à l'appelant fournir le tampon, au lieu de l'attribuer de manière dynamique.


Le retour d'un pointeur sur la mémoire allouée dynamique est pas par lui-même une fuite de mémoire. Une fuite de mémoire est quand il n'y a pas de variable de pointeur qui contient l'adresse de la mémoire allouée. Donc, aussi longtemps qu'un appelant sauve la valeur retournée dans une variable de pointeur, c'est bien - pas de fuite de mémoire. Mais votre propre code a des fuites de mémoire. À l'intérieur de votre boucle tandis que vous continuez à allouer la mémoire et à enregistrer l'adresse dans la variable chemin . En d'autres termes - vous continuez à écraser les informations sur la mémoire allouée précédemment et qui est une fuite de mémoire. Si vous avez un calloc dans la boucle, vous avez besoin d'un gratuit aussi.


3 Réponses :


0
votes

Vous pouvez demander à l'appelant de libérer la mémoire:

// in caller
char * s = find_path("/mypath", "command");
// do something about `s`
free(s);


0 commentaires

4
votes

C'est en effet l'un des problèmes de la propriété de la mémoire C. peut être assez difficile, car il n'y a pas de concepts Raii (essentiellement, pas de destructeurs automatiques) en C ++.

Je vois 3 solutions comment résoudre ce problème:

  • La pire solution du 3 est d'avoir un tampon statique global et de laisser votre fonction Find_Path remplir ce tampon et de renvoyer un pointeur à l'appelant. Cette astuce est utilisée par de nombreuses autres fonctions C standard C, mais il y a aussi beaucoup de problèmes avec celui-ci (souvent non thread-coffre-fort, et s'il s'agit de la sécurité du thread, l'appel suivant peut remplacer la valeur de retour précédente). Voir https://en.cppreference.com/w/cpp/uttility/programme / getenv pour une fonction qui a ce comportement (regardez les avertissements sur le dessus).
  • Une solution légèrement meilleure est documenter la valeur de retour de votre fonction et indiquez clairement à l'appelant qu'il est de sa responsabilité de libérer le pointeur retourné. S'il ne reçoit pas une fuite de mémoire. Voir https://fr.cppreference.com/w/c/experimental/dynamic / strdup pour une fonction qui utilise ce comportement.
  • Une autre solution consiste à faire passer un tampon à votre fonction avec une taille maximale. Donc au lieu de retourner un char * , vous ajoutez char * et Taille_t arguments ( taille_t indiquant la taille de la taille de la char * tampon en caractères). Ensuite, votre fonction Find_Path peut remplir ce tampon. Voir https://fr.cppreference.com/w/cpp/string/byte / strncpy pour une fonction avec ce comportement. Le problème avec cette approche est que si le tampon n'est pas assez gros, votre fonction doit renvoyer une défaillance et l'appelant doit passer un tampon plus grand. Certaines fonctions de Windows résolvent cela en ayant la fonction renvoyant une taille de tampon "attendue", donc si l'appel échoue (car le tampon n'est pas assez grand), l'appelant peut utiliser la valeur de retour pour voir la taille du tampon et allouer un plus grand tampon.

    Ma solution préférée dépend du cas réel. Je prendrais la troisième alternative s'il existe une taille de tampon maximale significative (comme par exemple un chemin de fichier maximum). Je prendrais la deuxième alternative est une taille tampon maximale est difficile à prédire. En tout cas, je n'utiliserais jamais la première alternative.


3 commentaires

Pour votre première solution, vous voudrez peut-être utiliser le stockage local du fil pour le faire du thread-Safe.


À mon avis, la deuxième option (c'est la responsabilité de l'appelant à la liberté) est la façon de faire de cela. Il suffit de regarder malloc / calloc: il renvoie un pointeur et c'est votre responsabilité de la libérer. Comme chaque fonction qui renvoie un pointeur vous dit de le libérer (à l'aide d'une fonction spécifique ou de libre), et c'est logique. Pour la dernière partie de votre réponse, s'il y a une taille de tampon maximum significatif, pourquoi la déranger est-elle allouée? Juste donner un tampon statique.


@ Tom's - masloc () et calloc () sont des cas spéciaux. Il n'existe aucun moyen de revenir (un pointeur à) la mémoire de taille arbitraire allouée de manière dynamique (dans le sens inconnu de l'appelant jusqu'au temps d'exécution) et être en mesure de s'assurer qu'il est libéré sans rendre l'appelant responsable de la libération . Pratiquement, les deux approches communes que je vois dans le code de production sont les deuxième et troisième. La plupart des temps, je vois le premier est le code écrit par un débutant qui ne comprend pas l'allocation de mémoire dynamique.



2
votes

Vous devez avoir gratuit code> dans deux endroits possibles.

  1. Vous devez libérer le chemin de chemin si cmd_exists code> renvoie false. li>
  2. Vous avez besoin d'avoir une méthode de téléphonie gratuite si cmd_existes code> retourne true. li> ol>

    1. strong> p> xxx pré>

    2. PRE>

     char *temp = find_path(...);
      .....//do your stuff
      if (temp) free(temp);
    


0 commentaires