Listes chainées et allocation mémoire [C] - C++ - Programmation
Marsh Posté le 12-11-2002 à 11:39:35
1) Oui, sans aucun doute permis.
2) Le free sert à libérer la mémoire, comme malloc l'a allouée. Donc, tu dois désallouer ta liste lorsque tu ne t'en sers plus.
Typiquement, crée une nouvelle fonction detruisListe, qui sera appellée par l'utilisateur (lorsqu'il n'a plus besoin d'une liste). Par contre, il ne faut pas désallouer la mémoire dans showList. Par définition, c'est une fonction qui ne modifie pas la liste (or désallouer, c'est détruire, donc par définition, c'est modifier).
3) Pas nécessairement. C'est peut-être le signe d'une très grosse occupation mémoire du programme, ou d'un plantage ailleurs. De toute façon, ce n'est pas une fuite mémoire qui peut faire planter un programme lorsqu'il se termine (par contre, en cours d'exécution, parce que la machine manque de mémoire, je ne dis pas).
Petit conseil supplémentaire : si tu n'as pas de type booléen sous la main, crée t-en un :
Code :
|
Par contre, ton paramètre yesno dans la fonction createPixel est une mauvaise idée. Il faut toujours initialiser tes champs, et si tu ne sais pas à quelles valeurs initialiser, initialise à zéro.
Marsh Posté le 12-11-2002 à 16:14:59
BifaceMcLeOD a écrit a écrit : Petit conseil supplémentaire : si tu n'as pas de type booléen sous la main, crée t-en un :
|
Pour ma culture, tu peux me dire a quoi ca sert ?
Car perso je trouve ca non seulement inutile, mais limite dangereux. Tant que tu ne t'en sers que dans des affectations, pas de probleme, mais si tu commences a ecrire des trucs comme ce qui suit, c'est euh...
Code :
|
sachant que si blabla = 2, par exemple, ca fera pas du tout ce que ca semble faire.
Marsh Posté le 12-11-2002 à 17:55:09
Je reconnais que cela n'apporte rien d'autre qu'une aide à la lecture (mais c'est déjà beaucoup).
Maintenant, si tu es rigoureux, tu sais que le "if" accepte un booléen (et pas un entier). Donc si "blabla" est de type booléen, il est inutile (voire, en C/C++, effectivement, dangereux) de le comparer avec une des 2 constantes booléennes pour obtenir un booléen, puisque c'en est déjà un.
Et c'est vrai dans tous les langages, pas seulement en C++. Exemple, en Java, écrire "if (isOpen == false) ..." est tout aussi stupide. Il faut écrire "if (!isOpen) ..." ; c'est plus simple, et toujours clair à lire et à transcrire dans une langue humaine ("if not is-open..." = "si ce n'est pas ouvert..." : c'est clair, non ?).
De toute façon, en C/C++, ce que j'ai donné revient à un simple #define, donc le problème que tu soulèves reste si on utilise 1 et 0 au lieu de TRUE et FALSE. La différence, c'est que quand tu lis BOOL dans le programme, c'est tout de suite plus clair que la variable derrière est booléenne. Et justement, ce sera une bonne raison pour ne pas faire de comparaison explicite dans le "if"...
Marsh Posté le 13-11-2002 à 00:04:31
Bonjour, me revoilà car j'ai un problème de compréhension :
Prenons cette fonction :
Code :
|
Si j'ajoute 1000 élements à ma liste, je vais créer 1000 fois un pointeur data* courant, il ne faut pas que je le désalloue ? Si je fais un free sur ce pointeur, je désalloue la mémoire pointée, donc *head c'est ca ?
Je viens de me rendre compte que ce que je viens de dire est idiot car dès que je sors de ma fonction, courant n'existe plus comme tout autre variable local à cette fonction ? Il ne faut donc pas désalloué courant sous peine de perdre *head, c'est ca ?
Je m'inquiete, je dois avoir un réel problème de conception de mon programme, car dès que je dépasse une certaine valeur de taille de données, mon processus est tué par le sytème. Je sais que mon algorithme est vraiment naif, mais c'est la première fois que je travaille avec des entités aussi "grosses, je n'ai donc jamais été confronté à ce genre de problèmes =)
Merci d'avance à tous !
A+
Marsh Posté le 13-11-2002 à 03:57:39
BifaceMcLeOD a écrit a écrit : Maintenant, si tu es rigoureux, tu sais que le "if" accepte un booléen (et pas un entier). |
Yep !
==true en C++ est tout aussi foireux que ==TRUE en C, mais c'est la comparaison inutile qui est en trop, pas le type booléen qui est très bien.
Marsh Posté le 13-11-2002 à 10:26:17
Evadream -jbd- a écrit a écrit : Bonjour, me revoilà car j'ai un problème de compréhension : Prenons cette fonction :
|
Attends, attends, j'ai peut-être été trop vite dans mes réponses hier.
Dans le principe, définir une fonction qui rassemble toutes les instructions qui initialisent un noeud, c'est bien. Maintenant, si la question, c'est "est-ce qu'appeler cette fonction createElement comme c'est fait ici, c'est approprié ?", la réponse est différente. Et je crains que ce soit non. Je détaille.
if( *head == NULL ){
Ici on suppose que head est un pointeur valide. Admettons. Si ce pointeur est NULL, on rentre dans le bloc "then" du "if". OK.
*head = createElement(0,0,0);
Par l'appel à createElement, on alloue de la mémoire et on l'initialise. Puis on afecte l'adresse de cette zone mémoire à la zone mémoire pointée par head, qui contient elle-même l'adresse d'une autre zone mémoire (double pointeur). OK.
*head = element;
On affecte l'adresse mémoire contenu dans element à *head. La précédente adresse que contenait *head est donc perdue, puisqu'on ne l'a pas gardée ailleurs ==> fuite mémoire. En l'occurrence, l'appel à createElement est ici inutile.
Maintenant, voyons ta question.
Si j'ajoute 1000 élements à ma liste, je vais créer 1000 fois un pointeur data* courant, il ne faut pas que je le désalloue ? Si je fais un free sur ce pointeur, je désalloue la mémoire pointée, donc *head c'est ca ?
Oui, dans le principe : si tu alloues, il y a un jour où tu devras désallouer. Mais ici, addql ne devrait pas avoir à faire d'allocation mémoire, car cette fonction suppose que tout est déjà alloué comme il faut : en particulier "element" qui est un pointeur valide sur une structure de type "data" .
Attention, par définition, un "pointeur courant" est un pointeur qui se balade sur des noeuds existants. On ne fait pas d'allocation directe dans ce pointeur, et donc on ne fait pas de désallocation dessus. Il est juste un moyen d'accéder aux différents élements d'une liste (ou d'une structure plus complexe).
Par contre, il est possible que tu doives faire des allocations dans des zones mémoires pointées par ton pointeur baladeur. Dans ce cas, ce sont tes noeuds qui reçoivent les adresses des nouvelles zones mémoires, pas ton pointeur baladeur lui-même.
Ici, si tu retires l'appel à "createElement", ta fonction "addql" me paraîtra correcte.
Marsh Posté le 13-11-2002 à 10:39:00
Clair, net et précis.
Encore merci pour tes explications !
Marsh Posté le 22-11-2002 à 01:14:55
Hello tout le monde !
J'ai tout remis à plat, et, on se moque pas... je ne désallouais pas la mémoire de mes listes lorsque je ne les utilisais plus...
J'ai fait des fonctions pour désallouer l'ensemble d'une liste ( et pas slt la tete.... ) et avec tous les conseils que j'ai eu, je suis arriver à un résultat propre !
Merci encore !
A+
Marsh Posté le 12-11-2002 à 02:02:07
Bonsoir tout le monde,
Je me remets au C à l'occasion d'un petit projet d'études, mais j'ai des problèmes très basiques en ce qui concerne la gestion de la mémoire.
Par exemple, ajout d'un élement en tête d'une liste chainée :
element est alloué grâce à la fonction qui suit avant de rentrer ds addql
Voici ma fonction createElement :
Ma structure data :
Pour afficher :
Voici donc mes questions :
- est-ce l'utilisation d'une fonction du type createElement est une bonne idée ou pas ?
- ou et quand faire des free dans mon cas ? Ci-dessus, dans le code de addql, si je mets un free(courant), je perds mon contexte et lorsque j'affiche ma liste avec showList, je boucle infiniment.
- je fais des free à la fin de mon main, mais lorsque je travaille sur des grosses listes, je suis sur d'avoir de groossses fuites de mémoire car mon programme est tué par le système après un gros swappage de dd (je travaille sous GNU/Linux).
Merci d'avance à tous et bonne soirée !
A+
Message édité par Evadream -jbd- le 12-11-2002 à 02:04:15