Comment utiliser strtok dans C correctement donc il n'y a pas de fuite de mémoire?
Je suis un peu confus par ce qui se passe lorsque vous appelez strtok sur un char pointeur en C. je sais qu'il modifie le contenu de la chaîne, de sorte que si je l'appelle strtok sur une variable appelée "ligne", son contenu va changer. Supposons que j'ai suivi le soufflet approche:
void function myFunc(char* line) {
//get a pointer to the original memory block
char* garbageLine = line;
//Do some work
//Call strtok on 'line' multiple times until it returns NULL
//Do more work
free(garbageLine);
}
Supposons que la "ligne" est malloced avant de passer à myFunc. Suis-je censé libérer la chaîne d'origine après l'utilisation de strtok ou faut-il faire le travail pour nous? Aussi, ce qui se passe si "ligne" n'est pas malloced et je tente d'utiliser la fonction ci-dessus? Est-il sécuritaire de faire ce qui suit à la place? (Suppose que le programmeur ne pas appeler gratuitement, s'il sait que la ligne n'est pas malloced)
Invocation
char* garbageLine = line;
myFunc(line);
free(garbageLine);
Définition de la fonction de
void function myFunc(char* line) {
//Do some work
//Call strtok on 'line' multiple times until it returns NULL
//Do more work
}
source d'informationauteur user246392
Vous devez vous connecter pour publier un commentaire.
strtok() ne sera pas gratuit quoi que ce soit, comme il n'a pas connaissance de cas où la chaîne est stockée. Il pourrait être sur la pile ou le tas, on ne sait pas ou soins! 🙂
Votre deuxième exemple est beaucoup mieux, car il simplifie mafonction(), et la rend utile dans des situations plus que la fonction n'a pas besoin de savoir où la chaîne est alloué. En supprimant l'appel à free() de mafonction() vous pouvez utiliser la fonction pour analyser les chaînes de la pile ou le tas. L'appelant alloue de la mémoire, l'appelant libère la mémoire!
Davantage de lecture:
strtok()
Dans le commentaire de votre question, vous dites que vous "Appel strtok sur la "ligne" plusieurs fois, jusqu'à ce qu'elle retourne NULL". Cela sonne comme si vous pouvez utiliser strtok de manière incorrecte. La première fois que vous l'appelez, vous devriez l'appeler avec la "ligne" comme argument; sur les appels suivants, vous devriez passer la valeur NULL. Prendre le suivant comme exemple:
Comme DrTwox dit, cependant, votre deuxième exemple est mieux "ligne" doit être libéré par le même contexte que malloced (ou pas), donc l'appel à free() n'appartient pas à cette fonction. Et vous êtes mieux de boucle - quelque chose comme:
Invocation est comme ceci:
La façon dont strtok œuvres est un peu complexe à expliquer, mais vous avez les pièces importantes - il n'a pas d'allouer ou libérer de la mémoire. Au lieu de cela, il fonctionne en modifiant la chaîne que vous avez passé.
strtok pas plus libère de la mémoire que strlen ne. Pourquoi voudriez-vous attendre d'elle? Ce mémoire ne serait-il libre? Peut-être que vous pensez strtok doit libérer de la mémoire, car il stocke un NUL, mais le contenu de la mémoire n'est pas pertinent. Lorsque vous allouez de la mémoire, l'allocation des pistes de la taille du bloc alloué, et le bloc entier est libéré lorsque les vous gratuit.
Qu'est-ce que avez à faire avec
strtok()
? Si vous allouer de la mémoire, vous devez la libérer. Lorsque votre application décide d'allouer et de libérer la mémoire est à vous. Mais si vous passez la mémoire destrtok()
qui ne fait aucune différence dans la mesure où si ou lorsque la mémoire est allouée ou libéré.Aussi longtemps que vous utilisez uniquement un "char*", il vous sera impossible de faire aucune manipulation de chaîne 100% en toute sécurité en raison de dépassements de la mémoire tampon.
Autant que les fuites de mémoire; si vous allouer il, la meilleure pratique est de le supprimer dans le même bloc (si possible). Cela signifie que si vous fournissez un strtok mise en œuvre, il faut supprimer toute la mémoire qu'il alloue à l'interne, mais pas de les supprimer de la mémoire transmis à la méthode.
Les raisons sont nombreuses fois, mais, fondamentalement, il n'ya aucune garantie que quelqu'un d'autre qui pourrait être à l'aide de votre méthode aurait accès à son code source, donc il y a peu de façon raisonnable, être prêt à regarder la mémoire allouée disparaître (provoquant une erreur de segmentation dans leur partie du code).
Pour faire un "coffre-fort" non-dépassement de la mémoire tampon de manipulation de chaîne, vous devez également avoir un maxium de la valeur du nombre. Par exemple, strncpy(...) prend un "nombre maximum de caractères en paramètre. Cela empêche certains types d'attaques où la mémoire "en aval" de la chaîne de l'allocation de la mémoire peut être rempli par des données qui est ensuite interprété comme du code par une autre partie du programme.
Cela signifie que votre
myFunc(char* line)
doit avoir une signaturemyfunc(char* line, int max_chars)
et l'ensemble de vos opérations suivantes doivent être garantismax_Chars + 1
quantité de mémoire pour fonctionner avec. Le plus on est de tenir la valeur null, ce qui pourrait ne pas être présent. En interne, vous devez vous assurer que toutes les opérations, comme strcpy fonctionnent uniquement sur la première max_chars (strncpy à le faire).Cela signifie que vous serez finalement toujours en faveur de l' "n" (nombre de caractères) de la version d'une chaîne de manipulateur pour le débordement de la mémoire tampon de sécurité. Le Couple qu'avec un fort "libérer dans le bloc que vous allouer" pratique et vous permettra d'éviter de 90% de la plupart de la chaîne liée à des erreurs de programmation.
Parfois vous voulez stocker une chaîne alloué pour plus tard (peut-être dans une carte). Avec des cas comme ceux-ci, vous devez prendre soin pour effacer la carte avant de quitter le programme, ou au moins de prendre quelque autre mesure à assurez-vous que la carte n'a pas la mémoire inutilisée plus que nécessaires.