OVH Cloud OVH Cloud

Leak dans string ?

11 réponses
Avatar
Frouin Jean-Michel
Bonjour je compile le programme suivant avec un leak detector maison qui
attrape les new et delete.
Mon programme main contient :

#include <string>

#ifdef LEAK_DETECTION
#include <leak/leak.h>
#endif

int main(int argc, char** argv)
{

std::string s;
s.assign("bob");
return 1;
}

J'obtient un leak :
delete : File : (null), Line : 0, Address : 0x804c200
et avec leaktracker (un outil de leak sous linux car je développe sous
linux donc avec g++ :
version gcc 4.0.3 (Ubuntu 4.0.3-1ubuntu5)
) :

# LeakReport
# from new @ | size # Pointer Addr
L 0xb7e1548a 16 # 0x804c200
# total allocation requests: 1 ; max. mem used 0 kBytes
# leak 16 Bytes :-(

Je ne comprends pas pourquoi il me reporte un leak ... peut être
j'utilise mal les string ?
Merci de me donner un coup de main :D

PS : Je suis en train de lire la fac C++ fr mais je ne vois pas la
réponse à ma question surtout que dedans je lis qu'il vaut mieux
utiliser les std::string plutot que les char* :D

10 réponses

1 2
Avatar
loufoque

Je ne comprends pas pourquoi il me reporte un leak ... peut être
j'utilise mal les string ?


C'est parce que la libstdc++ ne libère pas de suite la mémoire : elle la
garde pour une réutilisation future.

Avatar
Frouin Jean-Michel

Je ne comprends pas pourquoi il me reporte un leak ... peut être
j'utilise mal les string ?


C'est parce que la libstdc++ ne libère pas de suite la mémoire : elle la
garde pour une réutilisation future.


Bon mais alors comment je fais pour etre sur que ces libérations de la

libstdc++ ne correspondent pas à des leaks ?
Merci de votre aide !!

Mon leak logger est définit comme tel :


Les déclarations :

#ifndef _LEAK_H_
#define _LEAK_H_

extern const char *delete_FILE;
extern unsigned long delete_LINE;

#undef new
#undef delete

#include <cstdio>

#ifdef __cplusplus

void* operator new (size_t size, const char* name, const unsigned long
line);

void* operator new[] (size_t size, const char* name, const unsigned long
line);

void operator delete (void *);

void operator delete[] (void *ptr);

#ifdef DEBUG
#define DEBUG_NEW new(__FILE__, __LINE__)
#else
#define DEBUG_NEW new(__FILE__, __LINE__)
#endif
#define new DEBUG_NEW

#define delete delete_FILE=__FILE__; delete_LINE=__LINE__; delete

#endif

#endif

et le fichier de définitions :

#include <cstdio>
#include <cstdlib>

const char *delete_FILE = NULL;
unsigned long delete_LINE = 0;

#define _LOGFILE_ "leak.log"

void* operator new (size_t size, const char* name, const unsigned long line)
{
FILE* fp;
void* temp;
fp=fopen(_LOGFILE_,"a+");
fprintf(fp,"new : ");
//fprintf(fp,"%d @ ",size);
fprintf(fp,"File : %s, ",name);
fprintf(fp,"Line : %d, ",line);
temp = malloc(size);
fprintf(fp,"Address : 0x%x",(unsigned long)temp);
fprintf(fp," [Size : %d bytes] n",size);
fclose(fp);
return temp;
}

void* operator new[] (size_t size, const char* name, const unsigned long
line)
{
FILE* fp;
void* temp;
fp=fopen(_LOGFILE_,"a+");
fprintf(fp,"new[] : ");
fprintf(fp,"File : %s, ",name);
fprintf(fp,"Line : %d, ",line);
temp = malloc(size);
fprintf(fp,"Address : 0x%x",(unsigned long)temp);
fprintf(fp," [Size : %d bytes]n",size);
fclose(fp);
return temp;
}

void operator delete (void *ptr)
{
FILE* fp;
fp=fopen(_LOGFILE_,"a+");
fprintf(fp,"delete : ");
fprintf(fp,"File : %s, ",delete_FILE);
fprintf(fp,"Line : %d, ",delete_LINE);
fprintf(fp,"Address : 0x%x n",(unsigned long)ptr);
fclose(fp);
delete_FILE = NULL;
delete_LINE = 0;
free (ptr);
}


void operator delete[] (void *ptr)
{
FILE* fp;
fp=fopen(_LOGFILE_,"a+");
fprintf(fp,"delete[] : ");
fprintf(fp,"File : %s, ",delete_FILE);
fprintf(fp,"Line : %d, ",delete_LINE);
fprintf(fp,"Address : 0x%x n",(unsigned long)ptr);
fclose(fp);
delete_FILE = NULL;
delete_LINE = 0;
free (ptr);
}


Avatar
Alain Gaillard

Je ne comprends pas pourquoi il me reporte un leak ... peut être
j'utilise mal les string ?
Merci de me donner un coup de main :D


Tu utilises bien les string.
Peut être que ton outil de test n'analyse pas l'appel au destructeur à
la sortie du main.

Qu'est-ce qu'il te dit si tu fais:

void mafonction()
{
std::string s;
s.assign("bob");
}

int main(int argc, char** argv)
{
mafonction();
return 1;
}


Pourquoi return 1 au fait ?


PS : Je suis en train de lire la fac C++ fr mais je ne vois pas la
réponse à ma question surtout que dedans je lis qu'il vaut mieux
utiliser les std::string plutot que les char* :D


La FAQ a évidemment raison.

--
Alain

Avatar
Frouin Jean-Michel

Je ne comprends pas pourquoi il me reporte un leak ... peut être
j'utilise mal les string ?
Merci de me donner un coup de main :D


Tu utilises bien les string.
Peut être que ton outil de test n'analyse pas l'appel au destructeur à
la sortie du main.

Qu'est-ce qu'il te dit si tu fais:

void mafonction()
{
std::string s;
s.assign("bob");
}

int main(int argc, char** argv)
{
mafonction();
return 1;
}


Toujours la même chose ... il trouve un leak ...

Comment puis je faire pour analyser l'appel au destructeur ?
Pour l'instant mon outil est censé n'attraper que les new et delete
(avec leur equivalent []) que j'utilise et là manifestement il en
attrape d'autre que je n'utilise pas ...

Pourquoi return 1 au fait ?

Pourquoi pas :D



PS : Je suis en train de lire la fac C++ fr mais je ne vois pas la
réponse à ma question surtout que dedans je lis qu'il vaut mieux
utiliser les std::string plutot que les char* :D


La FAQ a évidemment raison.




Tiens dans mon leak logger j'utilise fopen, fprintf pour ecrire mon
fichier leak.log, si j'utilise std::ofstream de nouveau leak
apparaissent comme pour string
Donc j'ai l'impréssion que je vais avoir les memes soucis avec tous les
headers C++ (j'inclus <string> et <fstream>)
Donc ca serait bien que je trouve comment corriger mon leaker avant de
continuer :D à developper mon bout de code


Avatar
Alain Gaillard


Toujours la même chose ... il trouve un leak ...
Comment puis je faire pour analyser l'appel au destructeur ?


Franchement je ne sais pas.
Quand ta string sort de la portée, son destructeur est appelé
automatiquement. Je me disais que dans tu sortais du main, l'outil
n'analysait plus, mais manifestement ça n'est pas ça.


Pourquoi return 1 au fait ?

Pourquoi pas :D



C'est une raison en effet.
Bien sûr tu sais que tout ce qui n'est pas return 0 signale au système
que ton programme ne s'est pas exécuté correctement ?



--
Alain


Avatar
Jean-Marc Bourguet
Frouin Jean-Michel writes:

Je ne comprends pas pourquoi il me reporte un leak ...


Les objets de la bibliothèque standard utilisent souvent des
pools. Donc à moins que tu n'arrives à les forcer à rendre
toute la mémoire -- là regarde la doc de ton système --, il
est fort probable que tu voies comme leak de la mémoire qui
est toujours référencées par une variable statique et qui
serait réutilisé pour une autre chaîne.

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
loufoque

Mon leak logger est définit comme tel :


[snip]

Pourquoi ne pas utiliser des outils comme valgrind plutôt ?

Avatar
Frouin Jean-Michel

Mon leak logger est définit comme tel :


[snip]

Pourquoi ne pas utiliser des outils comme valgrind plutôt ?


Parceque je veux au passage en écrire un pour mieux comprendre les
subtilitée du C++ :D


Avatar
Frouin Jean-Michel


Toujours la même chose ... il trouve un leak ...
Comment puis je faire pour analyser l'appel au destructeur ?


Franchement je ne sais pas.
Quand ta string sort de la portée, son destructeur est appelé
automatiquement. Je me disais que dans tu sortais du main, l'outil
n'analysait plus, mais manifestement ça n'est pas ça.


Pourquoi return 1 au fait ?

Pourquoi pas :D



C'est une raison en effet.
Bien sûr tu sais que tout ce qui n'est pas return 0 signale au système
que ton programme ne s'est pas exécuté correctement ?





Oui je sais mais comme mon programme est un jeu de yatzee qui utilise
une IHM que je développe il n'entrera jamais dans un pipe :)
Mais tu as raison hop je change mon return 1; en return 0; et si on me
demande pourquoi je dirai !(pourquoi pas) :D



Avatar
Frouin Jean-Michel
Frouin Jean-Michel writes:

Je ne comprends pas pourquoi il me reporte un leak ...


Les objets de la bibliothèque standard utilisent souvent des
pools. Donc à moins que tu n'arrives à les forcer à rendre
toute la mémoire -- là regarde la doc de ton système --, il
est fort probable que tu voies comme leak de la mémoire qui
est toujours référencées par une variable statique et qui
serait réutilisé pour une autre chaîne.

A+



Bon ok :D j'ai modifié ma macro delete en sdelete avec un entier, si
l'entier est à 1 alors on attrape le delete sinon non :)
Du coup je n'ai plus de leak mais un soucis sur les adresses du style :


new : File : src/engine/engine.cpp, Line : 92, Address : 0x8053970
[Size : 8 bytes]
new : File : src/frames/mainframe.cpp, Line : 28, Address : 0x804d590
[Size : 28 bytes]
delete : File : src/frames/mainframe.cpp, Line : 34, Address : 0x804d820
delete : File : src/engine/engine.cpp, Line : 122, Address : 0x8053970

Donc ultime question :) puis je récupérer l'adresse du vrai pointeur ?
Car je créé une string à 0x804d590 et il me renvoie comme libérée à
0x804d820 :)

En tout cas un grand merci à tous le monde pour votre super réactivité !!


1 2