Libération mémoire....

[Résolu]
Signaler
Messages postés
278
Date d'inscription
mardi 22 janvier 2002
Statut
Membre
Dernière intervention
29 août 2006
-
Messages postés
700
Date d'inscription
mardi 30 décembre 2003
Statut
Membre
Dernière intervention
27 janvier 2009
-
Bonjour,

Voilà, j'ai une appli qui utilise énormément de mémoire, jai plusieurs listes chainées de plusieurs milliers d'enregistrements, de nombreuses classes et pas mal de tableaux de char * (des char ** quoi).
C'est la première fois que je fais un projet de cette envergure en C++ et là, j'avoue que je ne capte pas :
J'utilise les delete autant que je peux, mais apparemment, lorsque je regarde l'utilisation mémoire pendant que ça mouline, ça ne me libère rien du tout! Et j'ai VRAIMENT besoin de libérer de la mémoire...
je vous donne un ou 2 exemples :

Ligne * freePtrligne(Ligne * Ptrligne)
{
Ligne * t = NULL;
while(Ptrligne != NULL)
{
t = Ptrligne;
Ptrligne = Ptrligne->suivant;
delete t->champ;
delete t;
}
return NULL;
}

pour vider une liste chainee de char *

ou bien quand je veux libérer un char **, je fais "delete[] mavar;"
Si quelqu'un sait pourquoi ça va pas...

Merci!

12 réponses

Messages postés
700
Date d'inscription
mardi 30 décembre 2003
Statut
Membre
Dernière intervention
27 janvier 2009
4
non non avec delete bien utilisé pas de memory leak.
si tu fais 'char ** donnees = new char * [256];'
c'est 'delete [] donnees;' qu'il faut faire. mais si entre temps t'as fais 'donnees[i] = new char[quelequechose];', (et c'est ce qui est fait dans ta fonction split); avant de faire 'delete [] donnees;', tu dois faire une boucle qui fait 'delete [] donnes[i];'

note que quand la taille est fixe (cad connue a la compilation), t'as pas besoin d'allouer de la memoire avec new, ex: dans ton split tu peux remplacer 'char * newname = (char *) malloc(64);' par 'char newname[64];' (et la pas besoin de libération).
tu dois allouer de la memoire qd la taille n'est pas connue a la compilation (ex elle dépend d'une variable comme size_t), ou bien quand ce qui est retourné par une fonction c'est un pointeur vers quelque chose (dans ce cas le pointeur qui est retourné doit pointer vers une zone mémoire allouée grace a new)

voila si ca a pu t'eclairer...
a+ ;)
Messages postés
700
Date d'inscription
mardi 30 décembre 2003
Statut
Membre
Dernière intervention
27 janvier 2009
4
copie colle ici les endroits ou tu fais l'allocation (les new...).
a+ ;)
Messages postés
700
Date d'inscription
mardi 30 décembre 2003
Statut
Membre
Dernière intervention
27 janvier 2009
4
autre truc, comment tu sais que ca va pas?
sous vc++, pour detecter les memory leaks :
#include <crtdbg.h>

et au début de ton main :

_CrtSetDbgFlag( _CRTDBG_LEAK_CHECK_DF|_CRTDBG_ALLOC_MEM_DF );
_CrtSetReportMode(_CRT_ASSERT,_CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_ASSERT,_CRTDBG_FILE_STDERR);

la tu compiles ton programme, et tu fais Go (F5).

pour liberer avec delete, il faut que ton truc ait été alloué avec new et pas avec malloc ou quoi.
sinon t'as pas assez montré ton code pr k'je puisse t'en dire bcp plus...
a+ ;)
Messages postés
278
Date d'inscription
mardi 22 janvier 2002
Statut
Membre
Dernière intervention
29 août 2006

Bon, déjà, je vous montre pour l'allocation de la liste chainée dont je vous ai montré la libération:
Ltype * addnew(Type & t, Ltype * typ)
{
Ltype * tete = typ;
Ltype * nouveau = (Ltype *) malloc(sizeof(Ltype));
nouveau->typ = t;
nouveau->suivant = NULL;
if (typ == NULL)
typ = nouveau;
else
{
while (tete->suivant != NULL)
tete = tete->suivant;
tete->suivant = nouveau;
}
return typ;
}

effectivement, j'ai pas utilisé new, mais de mémoire, le new ne marche pas sur des structures définies dans le main().

Sinon, pour les char **, j'utilise uen fonciton split que j'ai développée, en gros, ça marche comme ça:
char ** donnees= NULL;
donnees	= split(ligne, limit, size_t);

et dans split :
char ** split(char * src, const char * car, int size_t = 0)	//Enlève les occurences de car dans src (renvoie t_result)
{
char ** t_result = NULL;
int i;
if (size_t == 0)
size_t= cpt_iteration(src, car);//cpt_iteration compte le nombre de car dans src
char * newname = (char *) malloc(64);
t_result = new char * [size_t];
for (i = 0; i<size_t; i++)
{
src = substr(src, car, newname);
t_result[i] = new char[64];
Trim(newname);
strncpy(t_result[i], newname, 64);
}
return t_result;
}


Voilà, j'espère que ça vous a éclairés sur mes erreurs...
Merci!
Messages postés
278
Date d'inscription
mardi 22 janvier 2002
Statut
Membre
Dernière intervention
29 août 2006

Oups! jme suis trompé dans la première fonction, C plutot ça:
Ligne * addligne(char * line, Ligne * Ptr)
{
Ligne * tete = Ptr;Ligne * nouveau (Ligne *) malloc(sizeof(Ligne));	nouveau->champ new char [512];
strncpy(nouveau->champ, line, 512);
nouveau->suivant = NULL;
if (Ptr == NULL)
Ptr = nouveau;
else
{
while (tete->suivant != NULL)
tete = tete->suivant;
tete->suivant = nouveau;
}
return Ptr;
}
Messages postés
700
Date d'inscription
mardi 30 décembre 2003
Statut
Membre
Dernière intervention
27 janvier 2009
4
ben voila c'etait ca le probleme... delete et malloc sont incompatibles t'as de la chance que ca n'ait pas planté.
remplace tous tes malloc par des new.

"effectivement, j'ai pas utilisé new, mais de mémoire, le new ne marche pas sur des structures définies dans le main()."
si si ca marche !!

definis tes structures dans un .h, et inclus ce .h dans les .c ou .cpp ou tu fais des new et des delete, et tu verrras pas de prob.

Si une zone a été alloué par ex en faisant 'char* a = new char[64]', il faudra faire 'delete [] a;' et non pas 'delete a;'.
'delete a;' est a faire si la zone avait été allouée en faisant 'char* a = new char;'. jcrois ke tu savais ca, mais vérifie le a tous les endroit ou tu liberes, si t'as pas mis les [] qd il en fallait ou l'inverse, ca peut mener a un plantage, ou au mieux a une mauvaise liberation.

voila, a+ ;)
Messages postés
3011
Date d'inscription
jeudi 26 septembre 2002
Statut
Membre
Dernière intervention
27 novembre 2004
8
c'est pas etonnant que ton programme fuis de tout les cotés !
Messages postés
278
Date d'inscription
mardi 22 janvier 2002
Statut
Membre
Dernière intervention
29 août 2006

Bon, alors c'est presque ça...
mainteannt, je sias ce qui fuit, ce sont mes char **
mais ce que je capte pas, c'est que je fais les fameux delete[], mais il me les libère pas du tout... ou alors j'ai zappé quelque chose.
si je fais un :
char ** donnees = new char * [256];
alors quand je delete, je dois faire :
delete[] donnees;
ou:
delete[] * donnees;
ou autre chose???
j'ai essayé les 2, et apparemment ça me libère pas plus de mémoire que ça...
exemple dans mon code :
char ** donnees = NULL;
donnees	= split(ligne, limit, size_t);
/*Traitement...*/
delete[] * donnees;


nan???
Si j'ai fais une enorme erreur, merci de me le dire... j'avais jamais touché à la libération mémoire en C++ avant...
Messages postés
117
Date d'inscription
samedi 12 avril 2003
Statut
Membre
Dernière intervention
8 septembre 2008

Pour supprimer des données, je te conseil la fonction free

par exemple ton tableau "char** donnees" pour le supprimer de la mémoire tu fais :

for(i=0; i<a; i++)
free(donnees[i]);
free(donnees);

>:) Stéph >:)
Messages postés
278
Date d'inscription
mardi 22 janvier 2002
Statut
Membre
Dernière intervention
29 août 2006

merci stepharcher, mais ça donne la meme chose, la différence avec delete[]C qu'on n'a pas besoin d'avoir utilisé new pour libérer la mémoire.

Bon, par contre, juste pour vérifier, quand on a utilisé delete[], on a un memory leak de 1 byte à quand meme chaques fois ou pas?

Sinon je comprends pas pourquoi j'ai ça...
Messages postés
278
Date d'inscription
mardi 22 janvier 2002
Statut
Membre
Dernière intervention
29 août 2006

Aaaaah! ben ouais! là c'est beaucoup plus clair!!!
Je dis pas que ça va marcher du premier coup, mais là j'a capté le truc!
ça va m'éviter des casse-tête tout ça ;)
dernière question, un peu naive : char * donnees[128], ça me crée la meme chose que char ** donnees = new char * [128] sans avoir besoin de delete???
Merci :))
Messages postés
700
Date d'inscription
mardi 30 décembre 2003
Statut
Membre
Dernière intervention
27 janvier 2009
4
'char * donnees[128];', est bien la meme chose que 'char ** donnees = new char * [128];', mais apres tu peux pas faire par exemple de 'return donnees;', a moins que donnees ne soit une variable globale. (en gros tu ne dois pas renvoyer dans une fonction un pointeur vers une variable qui est locale a ta fonction).
et effectivement qd tu fais char* donnees[128], pas besoin de libération (le tableau est alloué sur la base locale de ta procédure ou bien de la ou t'as ta derniere '{' , et est libéré automatiquement qd tu finis la procédure ou alors au moment ou tu sors de la ou t'étais en rencontrant un '}' ). dc qd tu connais la taille d'un tableau, et que celui ci ne sert que dans ta fonction ou procédure, ya que des inconvénients a utiliser new ou malloc a la place de ca.

a+ ;)