IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

MFC Discussion :

[MFC] A la chasse au memory leak


Sujet :

MFC

  1. #1
    Membre actif
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    258
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 258
    Points : 288
    Points
    288
    Par défaut [MFC] A la chasse au memory leak
    Bonjour tout le monde,

    Bon j'ai un application qui commence a devenir assez grosse (~15000 lignes) en MFC sous VC++6.0. Depuis le début j'ai eu la gestion de la mémoire en priorité. Et pourtant il persiste quelques memory leak dont un particulièrement bizarre.
    En fait au lancement mon appli charge un fichier en mémoire. Pour tester j'ai fais une simple dialog box avec un bouton pour charger le fichier et un pour désallouer tout ce que j'alloues au chargement du fichier.
    Voilà un ptit trace de ce que me donne ctrl+alt+suppr en terme de mémoire utilisée :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    2144  ko (déchargé)
    21732 ko (chargé)
    2372  ko (déchargé) ML : 228 ko
    21748 ko (chargé)
    2380  ko (déchargé) ML : 8 ko
    21752 ko (chargé)
    2384  ko (déchargé) ML : 4 ko
    21752 ko (chargé)
    2384  ko (déchargé) ML : 0 ko
    21768 ko (chargé)
    2400  ko (déchargé) ML : 16 ko
    21776 ko (chargé)
    2408  ko (déchargé) ML : 8 ko
    21780 ko (chargé)
    2412  ko (déchargé) ML : 4 ko
    21780 ko (chargé)
    2412  ko (déchargé) ML : 0 ko
    Bon que ca prenne 21Mo c'est tout à fait normal et c'est pas ca le prob. Le prob c'est que je charge un fichier dans un char*, et que quand je delete[] ce char* eh ben ca récupère pas toute la mémoire. Bon je peux vous montrer un peu de code mais rien d'extraordinaire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
     
    void CMonApp::Load()
    {
    	ifstream f;
    	f.open(Path,ios::binary);
     
    	if(!f.is_open())
    	{
    		// gestion de l'erreur (code inutile dans le cadre de ce problème
    	}
     
    	LoadDialog *Load_dlg = new LoadDialog;
    	Load_dlg->Create(IDD_LOAD,NULL);
    	Load_dlg->ShowWindow(SW_SHOW);
    	Load_dlg->UpdateWindow();
     
    	unsigned long len = theApp.File_GetSize(f);
    	unsigned long pos = 0;
     
    	Buffer     = new char[len+1];
    	Buffer_Len = len;
    	f.read(theApp.Buffer,len);
    	f.close();
     
    	Load_dlg->DestroyWindow();
     
    	// Là j'utilise le début du Buffer et donc j'en ai plus besoin, je le désalloue partiellement via :
     
    	Reloc(seek);
    }
     
    void CMonApp::Reloc(const int seek)
    {
    	int new_size = Buffer_Len-seek;
     
    	char * Temp_Buffer = new char[new_size+1];
     
    	memcpy(Temp_Buffer,Buffer+seek,new_size);
     
    	delete[] Buffer;
     
    	Buffer = new char[new_size+1];
     
    	memcpy(Buffer,Temp_Buffer,new_size);
     
    	Buffer_Len = new_size;
     
    	delete[] Temp_Buffer;
    }
     
    // Et voilà la fonction que j'utilise pour déchargé le tout de la mémoire :
     
    void CMonApp::UnLoad()
    {
    	if(Buffer)
    	{
    		delete[] Buffer;
    	}
    }
     
    // Par rapport au new fais dans la fonction Load et pour lequel il n'y a pas de delete il se trouve dans la classe :
    void LoadDialog::OnDestroy() 
    {
    	CDialog::OnClose();
     
    	delete this;
    }
    Je code sous VC++ 6.0, d'où peut venir le memory leak dans ce code ? (il n'y a que ce code qui est executé quand j'appuie sur les 2 boutons). Je précise que le trave est différent a chaque execution mais on retrouve toujours cette sorte de "cycle" (16 - 8 - 4 - 0). Une idée ?

  2. #2
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Points : 17 323
    Points
    17 323
    Par défaut
    salut ,
    dans ton source tu as la definition suivante dans l'entête ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif
    en mode debug trace est ce que vc dans l'onglet debug signal du leak en sortie de prog ?


  3. #3
    Membre actif
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    258
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 258
    Points : 288
    Points
    288
    Par défaut
    Oui :
    Citation Envoyé par VC++ 6.0
    Detected memory leaks!
    Dumping objects ->
    D:\Prog\MonApp\MonApp.cpp(493) : {204} client block at 0x00303030, subtype 0, 168 bytes long.
    a CDialog object at $00303030, 168 bytes long
    Object dump complete.
    La lignes 493 c'est un new que je fais sur un boîte de dialogue qui s'affiche juste après le chargement du fichier (c'est vrai j'ai oublié de le préciser) mais il y a bien dans le code une surcharge de l'évènement OnClose qui demande pour sauvegarder puis delete this. Donc bizarre

  4. #4
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Points : 17 323
    Points
    17 323
    Par défaut
    re,
    une chose comme ça ,quand tu fais cette sequence :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    LoadDialog *Load_dlg = new LoadDialog;
       Load_dlg->Create(IDD_LOAD,NULL);
       Load_dlg->ShowWindow(SW_SHOW);
       Load_dlg->UpdateWindow();
    apres le UpdateWindow(); vu que c'est pas modal ça continue directement derriere ,il n'y a pas d'attente .
    donc je comprends pas trop la logique de ce qui suit sauf si tu as allegé le code
    cette sequence me parait bizarre non?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    void LoadDialog::OnDestroy()
    {
       CDialog::OnClose();
    appeler OnClose dans OnDestroy() c'est plutot la fonction de la classe de base OnDestroy() non ?

  5. #5
    Membre actif
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    258
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 258
    Points : 288
    Points
    288
    Par défaut
    Citation Envoyé par farscape
    re,
    une chose comme ça ,quand tu fais cette sequence :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    LoadDialog *Load_dlg = new LoadDialog;
       Load_dlg->Create(IDD_LOAD,NULL);
       Load_dlg->ShowWindow(SW_SHOW);
       Load_dlg->UpdateWindow();
    apres le UpdateWindow(); vu que c'est pas modal ça continue directement derriere ,il n'y a pas d'attente .
    donc je comprends pas trop la logique de ce qui suit sauf si tu as allegé le code
    cette sequence me parait bizarre non?
    Le fichier fais 19 Mo c'est assez long à charger en mémoire donc j'ai une simple fenêtre avec un contrôle static qui dit "merci de patienter" et qui se détruit une fois le fichier chargé (c'est le read() qui prends entre 2 et 5 secondes).

    Citation Envoyé par farscape
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    void LoadDialog::OnDestroy()
    {
       CDialog::OnClose();
    appeler OnClose dans OnDestroy() c'est plutot la fonction de la classe de base OnDestroy() non ?
    C'est Visual qui m'a pondu ce code c'est pas moi. J'ai juste mit le delete moi

  6. #6
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Points : 17 323
    Points
    17 323
    Par défaut
    a mon avis tu as du changé en cours de route ,c'est CDialog::OnDestroy();
    qui est généré par defaut.

  7. #7
    Membre émérite
    Avatar de la drogue c'est mal
    Profil pro
    Inscrit en
    Novembre 2002
    Messages
    2 253
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2002
    Messages : 2 253
    Points : 2 747
    Points
    2 747
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    LoadDialog *Load_dlg = new LoadDialog;


    Load_dlg est détruit quand ?
    il y a du linge sur la corde à linge

  8. #8
    Membre actif
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    258
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 258
    Points : 288
    Points
    288
    Par défaut
    Citation Envoyé par la drogue c'est mal
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    LoadDialog *Load_dlg = new LoadDialog;


    Load_dlg est détruit quand ?
    Lors de l'appel Load_dlg->DestroyWindow() il y a un delete :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    void LoadDialog::OnDestroy()
    {
       CDialog::OnClose();
     
       delete this;
    }

    Citation Envoyé par farscape
    a mon avis tu as du changé en cours de route ,c'est CDialog::OnDestroy();
    qui est généré par defaut.
    Very Happy
    Ca m'étonne vraiment beaucoup c'est le genre de truc auquel je touche pas mais bon je vais voir dés que je peux (je ne suis plus sous win là ).

  9. #9
    Rédacteur
    Avatar de abelman
    Inscrit en
    Février 2003
    Messages
    1 106
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 1 106
    Points : 2 629
    Points
    2 629
    Par défaut
    Pour la fermeture du dialogue intercepte plutot WM_CLOSE au lieu de WM_DESTROY . Supprime la fonction OnDestroy et fais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void LoadDialog::OnClose()
    {
       DestroyWindow();
       delete this;
    }

  10. #10
    Membre actif
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    258
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 258
    Points : 288
    Points
    288
    Par défaut
    Tiens j'ai fais :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    void CWDA_LoadDialog::OnClose() 
    {
    	CDialog::OnClose();
     
    	delete this;
    }
    Au lieu de OnDestroy() et j'ai modifie le LoadDlg->DestroyWindow() en LoadDlg->SendMessage(WM_CLOSE); et a plus de memory leak

  11. #11
    Rédacteur
    Avatar de abelman
    Inscrit en
    Février 2003
    Messages
    1 106
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 1 106
    Points : 2 629
    Points
    2 629
    Par défaut
    oui car CDailog::OnClose par défaut appelle DestroyWindow()

  12. #12
    Membre émérite
    Avatar de la drogue c'est mal
    Profil pro
    Inscrit en
    Novembre 2002
    Messages
    2 253
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2002
    Messages : 2 253
    Points : 2 747
    Points
    2 747
    Par défaut
    mon dieux j'avais pas vu .... c'est à l'epita qu'on t'as appris à faire ca ??


    parce que limite tout pourri ca
    il y a du linge sur la corde à linge

  13. #13
    Membre actif
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    258
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 258
    Points : 288
    Points
    288
    Par défaut
    Citation Envoyé par la drogue c'est mal
    mon dieux j'avais pas vu .... c'est à l'epita qu'on t'as appris à faire ca ??


    parce que limite tout pourri ca
    Etant donné que j'y suis pas encore (seulement a cette rentrée) non ca n'est pas là qu'on me l'a appris. Limite tout pourri ? Sachant que je ne peux pas delete directement l'objet depuis le code je n'ai pas le choix. Si tu as mieux n'hésite pas ...

  14. #14
    Membre émérite
    Avatar de la drogue c'est mal
    Profil pro
    Inscrit en
    Novembre 2002
    Messages
    2 253
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2002
    Messages : 2 253
    Points : 2 747
    Points
    2 747
    Par défaut
    Sachant que je ne peux pas delete directement l'objet depuis le code
    et pourquoi ?
    il y a du linge sur la corde à linge

  15. #15
    Membre actif
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    258
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 258
    Points : 288
    Points
    288
    Par défaut
    Ben avec une fenêtre non-modale ton code continue et tu ne sais jamais quand il ne faudra plus utiliser l'objet sauf si tu surveille l'event OnClose() où tu sais que tu peux delete sans problème ton objet ...

  16. #16
    Membre émérite
    Avatar de la drogue c'est mal
    Profil pro
    Inscrit en
    Novembre 2002
    Messages
    2 253
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2002
    Messages : 2 253
    Points : 2 747
    Points
    2 747
    Par défaut
    si tu veux faire ca, fais le dans le bon message. Surcharge la methode virtuel PostNcDestroy() ( de la classe CWnd ). Comme c'est ecrit dans le msdn, c'est fait pour ca :

    Derived classes can use this function for custom cleanup such as the deletion of the this pointer.
    PostNcDestroy est fait expres pour implémenter les delete this.
    il y a du linge sur la corde à linge

  17. #17
    Rédacteur
    Avatar de abelman
    Inscrit en
    Février 2003
    Messages
    1 106
    Détails du profil
    Informations forums :
    Inscription : Février 2003
    Messages : 1 106
    Points : 2 629
    Points
    2 629
    Par défaut
    Tu peux bien sur faire un delete sur l'objet dialog, si tu en fais un membre de ta classe (delete dans le destructeur) et non une variable locale à une fonction

  18. #18
    Membre actif
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    258
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 258
    Points : 288
    Points
    288
    Par défaut
    Citation Envoyé par abelman
    Tu peux bien sur faire un delete sur l'objet dialog, si tu en fais un membre de ta classe (delete dans le destructeur) et non une variable locale à une fonction
    Certes mais ca veut dire attendre la fin du programme (puisque c'est la classe de l'objet theApp) avant de libérer la mémoire.

    Citation Envoyé par la drogue c'est mal
    si tu veux faire ca, fais le dans le bon message. Surcharge la methode virtuel PostNcDestroy() ( de la classe CWnd ). Comme c'est ecrit dans le msdn, c'est fait pour ca :

    Derived classes can use this function for custom cleanup such as the deletion of the this pointer.
    PostNcDestroy est fait expres pour implémenter les delete this.
    Merci je ne connaissais pas cette fonction Après tout on est tous là pour apprendre non ?

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 8
    Dernier message: 28/10/2010, 20h08
  2. Compilation TAO / Mfc : Memory Leaks
    Par Rolsct dans le forum CORBA
    Réponses: 4
    Dernier message: 17/04/2005, 19h13
  3. [MFC] Thread & memory leaks
    Par Racailloux dans le forum MFC
    Réponses: 7
    Dernier message: 15/03/2005, 12h44
  4. Memory leak en C/C++
    Par Roswell dans le forum Autres éditeurs
    Réponses: 6
    Dernier message: 07/07/2004, 19h41
  5. Réponses: 7
    Dernier message: 26/02/2004, 09h32

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo