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

C++Builder Discussion :

[XE4] où est la fuite de mémoire ?


Sujet :

C++Builder

  1. #1
    Membre éclairé
    Homme Profil pro
    Consultant technique
    Inscrit en
    Juillet 2002
    Messages
    519
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consultant technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2002
    Messages : 519
    Par défaut [XE4] où est la fuite de mémoire ?
    Bonjour,

    Je fais actuellement une petite application qui possède un ruban.
    Je me suis aperçu, qu'à chaque fois que j'ouvre et referme un fichier, la mémoire montait et ne redescendait pas complètement.
    Après différents tests, j'en suis arrivé au code suivant que j'ai collé sur un bouton pour le test.

    La boite de dialogue d'ouverture du fichier s'ouvre quand j'appuie mais je ferme la fenêtre sans ouvrir un fichier, j'ai l'impression que toute la mémoire n'est pas libéré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
    try {
    	OpenFile1 = new TOpenDialog(Form1);
    	if (OpenFile1 != NULL)
    	   {
    	   if (OpenFile1->Execute())
    		  {
    		  //LoadFile(OpenFile1->FileName);
    		  }
    	   }
    	}
    __finally {
    	      if (OpenFile1 != NULL)
                 {
                 delete OpenFile1;
                 OpenFile1 = NULL;
                 }
    	  	  }
    Résultat :
    Dans l'observateur d'évènement je regarde la zone "mémoire (jeu de travail privée)".
    1) à l'ouverture : 3696K
    2) appuie sur le bouton (ouverture de la boite de dialogue) : 8452K
    3) de retour sur l'application : 7688K
    2) appuie sur le bouton (ouverture de la boite de dialogue) : 9156K
    3) de retour sur l'application : 8692K
    2) appuie sur le bouton (ouverture de la boite de dialogue) : 9584K
    3) de retour sur l'application : 9200K

    Très rapidement on arrive à plus de 14M alors que l'on a réellement rien fait.
    Code guard n'indique pas de fuite de mémoire tout comme la directive ReportMemoryLeaksOnShutdown.
    D'ailleurs, si j'active cette directive, il y a encore beaucoup plus de mémoire de consommée.
    Si je regarde le "différentiel de la plage de travail (mémoire)", je vois que la quantité allouée est toujours supérieure à la quantité libérée.


    Savez-vous de quoi cela peut venir ?

    Merci.

  2. #2
    Membre Expert
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Responsable de compte
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Billets dans le blog
    1
    Par défaut
    Salut

    Lors de la création de l'objet OpenFile1 tu luis attribue comme propriétaire La form même
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    OpenFile1 = new TOpenDialog(Form1);
    de ce fait c'est ta Form lors de sa destruction qui sera chargée de la destruction de l'object et non toi

    si tu veux gérer toi même la mémoire tu dois créer l'objet de cette manière

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    OpenFile1 = new TOpenDialog(NULL);

    cdlt
    vous trouverez mes tutoriels à l'adresse suivante: http://djmsoftware.developpez.com/
    je vous en souhaite une excellente lecture ...

    A lire : Les règles du forum

  3. #3
    Membre éclairé
    Homme Profil pro
    Consultant technique
    Inscrit en
    Juillet 2002
    Messages
    519
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consultant technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2002
    Messages : 519
    Par défaut
    Merci pour cette piste mais malheureusement, cela ne change rien.

    Si je met NULL, les chiffres sont les mêmes.

    Au départ, j'ai utilisé un TActionManager avec une action standard d'ouverture de fichier.
    En voyant la montée en mémoire anormale, j'ai essayé de réduire le code au minimum pour trouver d'où vient cette consommation.

    Le problème se produit en debug et release tout comme en x86 que x64.

    Le code suivant ne pose pas de perte de mémoire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    OpenFile1 = new TOpenDialog(NULL);
    delete OpenFile1;
    OpenFile1 = NULL;

    Par contre, le code suivant fait augmenté la mémoire consommée.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    OpenFile1 = new TOpenDialog(NULL);
    OpenFile1->Execute();
    delete OpenFile1;
    OpenFile1 = NULL;
    J'en déduis que c'est l'appel à execute() le problème.
    Si je lance l'appel 5 fois d'affilé, j'ai toujours le même phénomène en 5 fois plus important.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    OpenFile1 = new TOpenDialog(NULL);
    OpenFile1->Execute();
    OpenFile1->Execute();
    OpenFile1->Execute();
    OpenFile1->Execute();
    OpenFile1->Execute();
    delete OpenFile1;
    OpenFile1 = NULL;
    Au final, ce ne serait donc pas la gestion de la vie du composant le soucis.

    Avez-vous une nouvelle idée ?

    Merci.

  4. #4
    Membre très actif Avatar de nirgal76
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2007
    Messages
    924
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 924
    Par défaut
    mais OpenFile1 il sort d'ou ? c'est une variable de ta classe (genre TOpenDialog* OpenFile1) ou un composant vcl déposé sur la fiche (et dans ce cas, ne pas faire de new ni delete, l'objet est géré par la fenêtre)
    vu son nom, "OpenFile1", j'ai l'impression que c'est un composant déposé sur la fenêtre.

  5. #5
    Membre éclairé
    Homme Profil pro
    Consultant technique
    Inscrit en
    Juillet 2002
    Messages
    519
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consultant technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2002
    Messages : 519
    Par défaut
    C'est une variable de ma classe.
    Je l'ai nommé comme le 1er composant que l'on pose sur la fiche car j'ai d'abord fait un test avec ce composant avant de le supprimer.
    Ensuite, j'ai créé une variable ayant le même nom pour ne pas changer le code.

    Je veux bien changer le nom de la variable mais cela ne changera rien au résultat.

  6. #6
    Membre Expert
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Responsable de compte
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Billets dans le blog
    1
    Par défaut
    Avant d'ouvrir un cas chez Emnarcadero Assure toi que le composant TOPenDialog que tu avait placé sur ra fiche n'est plus référé dans ton .h
    tu peux encore tenter un autre essai du style un composant local à ta Procédure du genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
     
    TOpenDialog* MyDialog= new TOpenDialog(NULL);
    MyDialog->Execute();
    delete MyDialog;
    cdlt
    vous trouverez mes tutoriels à l'adresse suivante: http://djmsoftware.developpez.com/
    je vous en souhaite une excellente lecture ...

    A lire : Les règles du forum

  7. #7
    Membre émérite
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    573
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 573
    Par défaut
    Salut

    Peut etre une solution , çà proviendrait de la fragmentation de la memoire utilisée par le processus : http://www.experts-exchange.com/Prog..._21521143.html

    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
     
    First, Windows allocate and free the used memory when is neccesary (or when it wants...)
    When you free the Opendialog, the memory of your process is fragmented and is Windows who decides when compact it.
    So... We can force this process of defrag the memory with:
     
      SetProcessWorkingSetSize(GetCurrentProcess, $FFFFFFFF, $FFFFFFFF);
     
    so... you can use the Opendialog created dinamically (instead of place a Opendialog component visually in your form), use it, free it and later execute this call for defrag the memory.
    Here you have an example:
     
    procedure TForm1.Button1Click(Sender: TObject);
    var
      OD : TOpenDialog;
    begin
      OD:=TOpenDialog.Create(Self);
      try
        OD.InitialDir:='c:\windows';
        If OD.Execute then Caption:=OD.FileName;
      finally
        OD.Free
      end;
     
      //Now, We compact the process memory:
      SetProcessWorkingSetSize(GetCurrentProcess, $FFFFFFFF, $FFFFFFFF);
     
    end;
    Un peu plus loin , ils parlent de IMallocSpy , çà pourrait t aider aussi .

    Voir ici pour son utilisation : http://nachbar.name/2009/10/04/imall...uilder-cb2009/

  8. #8
    Membre éclairé
    Homme Profil pro
    Consultant technique
    Inscrit en
    Juillet 2002
    Messages
    519
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Consultant technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2002
    Messages : 519
    Par défaut
    Merci, c'est une bonne info.

    J'ai créé un nouveau projet VCL et j'ai juste ajouter un bouton et mis le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    TOpenDialog* MyDialog= new TOpenDialog(NULL);
    MyDialog->Execute();
    delete MyDialog;
    SetProcessWorkingSetSize(GetCurrentProcess, 0xFFFFFFFF, 0xFFFFFFFF);
    Mémoire :
    Au démarrage : 1696K
    Après lancement du code : 6156K
    Après un 2ème lancement de la fonction : 6868K

    J'ai regardé avec process monitor quand on utilise cette fonction.
    Il y a plein de buffer overflow. En voici un extrait.
    Nom : Bufferoverflow.png
Affichages : 173
Taille : 10,2 Ko

    La fuite de mémoire vient de là.

    Donc, les fonctionnements de bases ne sont pas correctement gérés dans cette version.
    Je comprends mieux pourquoi ils utilisent cette instruction dans certains de leur exemples.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ReportMemoryLeaksOnShutdown = true;
    Je crois que je vais arrêter avec cette version, il y a vraiment trop de bugs pour gérer des logiciels en production et revenir sur des versions antérieures.

    D'ailleurs dans la version XE6, ils ont corrigé un paquet de fuite mémoire.
    http://edn.embarcadero.com/article/43754

    Merci pour votre aide.

  9. #9
    Membre Expert
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Responsable de compte
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Billets dans le blog
    1
    Par défaut
    Salut
    J'ai regardé avec process monitor quand on utilise cette fonction.
    Il y a plein de buffer overflow. En voici un extrait.
    Conclusion trop hâtive
    En Effet il est fréquent q'avec les API Win 32 que lors de l'appel d'une fonction nécessitant un Buffer pour stocker les informations en retour
    la taille du Buffer ne soit pas connue , lors du retour de la fonction l'API retourne un message d'erreur de ce type et dans une des variables la taille du Buffer nécessaire
    lors du 2 em Appel de la fonction avec la taille correcte il ni a plus d'erreurs
    c'est manifestement ce que te retourne ton outil de supervision

    l'erreur doit se trouver ailleurs, le Buffer n'est peut être pas libéré

    Cdlt
    vous trouverez mes tutoriels à l'adresse suivante: http://djmsoftware.developpez.com/
    je vous en souhaite une excellente lecture ...

    A lire : Les règles du forum

  10. #10
    Membre Expert
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Responsable de compte
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Billets dans le blog
    1
    Par défaut
    Salut
    j'ai poussé un peu plus loin l'analyse
    ma conclusion est que ce comportement est Normal en effet le design par Microsoft l'a prévu ainsi
    pour appuyer mes dire essaye le code suivant qui utilise les API MS et tu t'apercevra qu'il en est de même
    d'autre part ce composant crée 12 Threads qui sont libérés automatiquement mais non à la libération du composant
    code d'essai
    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
     
    	HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED |
    		COINIT_DISABLE_OLE1DDE);
        if (SUCCEEDED(hr))
    	{
    		IFileOpenDialog *pFileOpen;
     
    		// Create the FileOpenDialog object.
    		hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_ALL,
    				IID_IFileOpenDialog, reinterpret_cast<void**>(&pFileOpen));
     
    		if (SUCCEEDED(hr))
    		{
    			// Show the Open dialog box.
    			hr = pFileOpen->Show(NULL);
     
    			// Get the file name from the dialog box.
    			if (SUCCEEDED(hr))
    			{
    				IShellItem *pItem;
    				hr = pFileOpen->GetResult(&pItem);
    				if (SUCCEEDED(hr))
    				{
    					PWSTR pszFilePath;
    					hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath);
     
    					// Display the file name to the user.
    					if (SUCCEEDED(hr))
    					{
    						MessageBox(NULL, pszFilePath, L"File Path", MB_OK);
    						CoTaskMemFree(pszFilePath);
    					}
    					pItem->Release();
    				}
    			}
    			pFileOpen->Release();
    		}
    		CoUninitialize();
       }
    cdlt
    vous trouverez mes tutoriels à l'adresse suivante: http://djmsoftware.developpez.com/
    je vous en souhaite une excellente lecture ...

    A lire : Les règles du forum

Discussions similaires

  1. Problème mémoire : où est la fuite ?
    Par MetalF dans le forum Général Java
    Réponses: 2
    Dernier message: 09/07/2010, 12h04
  2. Réponses: 1
    Dernier message: 02/12/2005, 15h18
  3. fuite de mémoire
    Par mamag dans le forum MFC
    Réponses: 17
    Dernier message: 19/08/2005, 11h42
  4. Fuite de mémoire en utilisant le template list
    Par schtroumpf_farceur dans le forum Langage
    Réponses: 9
    Dernier message: 18/07/2005, 21h44
  5. Réponses: 8
    Dernier message: 17/10/2002, 13h52

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