quand libérer le pointeur en C et comment savoir s'il est libéré
Je suis nouveau en C, en essayant de comprendre au sujet de l'allocation de la mémoire en C que j'ai un peu confus
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int a;
} struct1_t;
int main()
{
funct1(); //init pointer
return 1;
}
int funct2(struct1_t *ptr2struct)
{
printf("print a is %d\n",ptr2struct->a);
//free(ptr2struct);
printf("value of ptr in funct2 is %p\n", ptr2struct);
return 1; //success
}
int funct1(){
struct1_t *ptr2struct = NULL;
ptr2struct = malloc(sizeof(*ptr2struct));
ptr2struct->a = 5;
printf("value of ptr before used is %p", ptr2struct);
if (funct2(ptr2struct) == 0) {
goto error;
}
free(ptr2struct);
printf("value of ptr in funct1 after freed is is %p\n", ptr2struct);
return 1;
error:
if(ptr2struct) free(ptr2struct);
return 0;
}
J'ai funct 1 qui appelle funct 2, et après l'utilisation de l'allocation d'un pointeur dans funct1, j'ai essayer de libérer le pointeur. Et je créer un cas où, si la valeur de retour dans funct2 n'est pas 1, puis essayez à nouveau de libérer le pointeur à l'.
Ma question est ci-dessous
dont la pratique est mieux, si je dois libérer de la mémoire, dans funct2 (après je le passe) ou dans funct1 (après que j'ai fini l'obtention de la valeur de retour de funct1)
La deuxième chose, c'est de savoir si c'est correct de faire un goto erreur, et l'erreur:
if(ptr2struct) free(ptr2struct);
Ma troisième question est , comment puis-je vérifier si la valeur allouée est déjà libéré ou pas? parce que, après l'obtention de la valeur de retour, je libère le pointeur, mais si j'ai l'impression, elle montre le même emplacement et avec l'allocation d'un (donc pas un pointeur null).
source d'informationauteur xambo
Vous devez vous connecter pour publier un commentaire.
1) dois-je libre dans la fonction d'appel ou dans la fonction appelée?
J'essaie de faire le libre-ing dans la même fonction que le malloc-ing. Ce garde la mémoire-les problèmes de gestion dans un seul endroit et donne également une meilleure séparation des préoccupations, car la fonction appelée dans ce cas peut également travailler avec des pointeurs qui n'ont pas été malloc-ed ou d'utiliser le pointeur de même deux fois (si vous voulez le faire).
2) Est-il correct de faire un "goto erreur"?
Oui! En sautant à un seul endroit à la fin de la fonction vous éviter d'avoir à dupliquer les ressources de libération de code. C'est un modèle courant et n'est pas mauvais depuis le "goto" est de servir comme une sorte de "return" et n'est pas de faire l'un de ses vraiment délicat et mal de trucs, il est plus connu pour.
C++, d'autre part, est un moyen sympa de faire ce genre de gestion des ressources. Depuis destructeurs sont de façon déterministe appelée juste avant une fonction se termine, ils peuvent être utilisés à proprement paquet de ce roi de la gestion des ressources. Ils appellent cette technique RAII
Une autre façon d'autres langues ont de traiter cette question est finalement de blocs.
3) puis-je voir si un pointeur a déjà été libérée?
Malheureusement, vous ne pouvez pas. Ce que certaines personnes ne se paramètre le pointeur de la valeur de la variable à NULL après la libération. Il ne fait pas de mal (depuis son ancienne valeur ne doit pas être utilisé après avoir été libéré de toute façon) et il a la belle propriété de libérer un pointeur null est spécifié pour être un no-op.
Cependant, cela n'est pas infaillible. Soyez prudent sur le fait d'avoir d'autres variables de l'aliasing le même pointeur, car ils contiennent encore de l'ancienne valeur, qui est maintenant un dangereux balançant pointeur.
Appeler free() sur un pointeur ne change pas, seules les marques de mémoire libre. Votre pointeur se pointent toujours vers le même emplacement qui contiennent la même valeur, mais cette valeur peut maintenant être écrasé à tout moment, de sorte que vous ne devez jamais utiliser un pointeur après il est libéré. Pour s'assurer que, il est toujours une bonne idée de définir le pointeur à NULL après libre avec elle.
C'est une "propriété" de la question. Qui est propriétaire de la mémoire allouée. Généralement, cela doit être décidé en fonction de la conception de votre programme. Par exemple, le seul but de func1() pourrait être seulement allouer de la mémoire. C'est, de la mise en œuvre, func1() est la fonction pour l'allocation de mémoire et puis la "vocation" de la fonction utilise la mémoire. Dans ce cas, la propriété de libérer la mémoire est à l'appelant de func1 et PAS avec func1().
Dans ce cas, vous pouvez utiliser goto et élégamment gratuit seulement ce mémoire qui a été allouée jusqu'au point de la configuration a échoué.
Cependant, il suffit de dire que dans votre exemple goto est facilement évitable et doit être évitée.
Facile. Définir la mémoire libérée comme NULL. L'autre avantage, à l'exception de celle mentionnée par MK, est que le passage de pointeur NULL à la libre volonté de provoquer un NOP c'est à dire aucune opération n'est effectuée. Ce sera également vous aider à éviter tout double supprimer les problèmes.
Ce que je suis sur le point de partager mes propres pratiques de développement en C. Ils sont qui n'en est PAS la SEULE façon d'organiser vous-même. Je suis juste en indiquant un moyen de ne pas la.
Ok, donc, à bien des égards "C" est un langage perdu, de sorte que beaucoup de discipline et de rigueur qui vient de soi en tant que développeur. J'ai mis au point "C" pour les plus de 20 ans, professionnellement, je n'ai que très rarement, je n'ai eu à vous fixer une production de qualité des logiciels que j'ai développés. Bien que tout à fait un peu de le succès peut être attribué à l'expérience, une bonne partie de elle est enracinée dans une pratique cohérente.
- Je suivre un ensemble de pratiques de développement, qui sont assez vastes, et tout aussi trivial que les onglets des conventions de nommage et de ce pas. Je vais limiter mon auto à ce que je fais à propos des relations avec les structures en général et il y a la gestion de la mémoire en particulier.
Si j'ai une structure qui est utilisée dans le logiciel, j'écris créer/détruire; init/fait des fonctions de type:
et d'allouer et désallouer la structure de ces fonctions.
Si je manipule un des éléments de structure directement tous sur le programme, puis ne pas typedef. - Je prendre la peine d'utiliser le mot-clé struct dans chaque déclaration pour que je sache que c'est une structure. Cela est suffisant où le seuil de la douleur n'est PAS tellement que je voudrais obtenir ennuyé par elle. 🙂
Si je trouve que la structure est TRÈS bien comme un objet puis-je choisir de manipuler les éléments de structure STRICTEMENT par le biais d'un opaque API; puis-je définir son interface à travers set/get type de fonctions pour chaque élément, j'ai créer une "déclaration anticipée" dans le fichier d'en-tête utilisés par toutes les autres parties du programme, créer un opaque définition de type du pointeur de la structure, et seulement déclarer la structure réelle de la structure de l'API de mise en œuvre de fichier.
foo.h:
foo.c:
Vous verrez une ressemblance frappante entre l'approche que j'ai décrites ci-dessus et de la programmation orientée objet. Il est destiné à être que ...
Si vous gardez vos interfaces propre comme cela, si oui ou non vous devez définir les variables d'instance NULL tous sur la place n'a pas d'importance. Le code permettra, je l'espère, le rendement lui-même à un resserrement de la structure où des erreurs stupides sont moins susceptibles.
Espère que cette aide.
Je sais que c'est une réponse, mais, je voulais donner à mon entrée. Comme je le comprends, quand vous appelez une fonction avec des paramètres tels que ici (le pointeur), les paramètres sont transmis à l' pile(FILO).
Donc le pointeur passé à la fonction sera automatiquement sauté hors de la pile, mais pas de libérer le pointeur dans funct1(). Par conséquent, vous auriez besoin de libérer le pointeur dans funct1() Corrigez-moi si je me trompe.