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

Composants VCL Delphi Discussion :

VirtualTreeView et gestion mémoire


Sujet :

Composants VCL Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre émérite
    Avatar de free07
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2005
    Messages
    942
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ardèche (Rhône Alpes)

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

    Informations forums :
    Inscription : Mars 2005
    Messages : 942
    Par défaut VirtualTreeView et gestion mémoire
    Bonjour

    J'ai un programme qui utilise VirtualTreeView pour l'affichage d'une liste d'objet ( avec TObjectList), les objets sont ajoutés au VirtualTreeView par AddChild et c'est lui qui en est propriétaire.

    OwnsObjects de TObjectList est à False car c'est le VirtualTreeView qui libère la mémoire de la liste des objets lorsqu'il est détruit.

    Mais dans certains cas, j'aimerai pouvoir maitriser complètement la libération des objets de la liste : est il possible d'indiquer au VirtualTreeView de ne pas s'occuper de la libération mémoire ? dans ce cas, je pourrai mettre OwnsObjects à True et ce sera le TObjectList qui libérera la mémoire.

    J'ai cherché sur le net mais je n'ai pas trouvé l'info.

  2. #2
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 124
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 124
    Par défaut
    Il me semblait que le TVirtualTreeView gérait des pointeurs comme UserData et pas des objets
    Faut dire que je ne l'ai jamais utilisé, j'ai regardé par curiosité en C++Builder, il y a dix ans.

    D'ailleurs, à l'époque tout était TVirtualNode \ PVirtuaNode soit des record, la donnée utilisateur était dedans
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Membre émérite
    Avatar de free07
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2005
    Messages
    942
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ardèche (Rhône Alpes)

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

    Informations forums :
    Inscription : Mars 2005
    Messages : 942
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Il me semblait que le TVirtualTreeView gérait des pointeurs comme UserData et pas des objets
    Oui c'est vrai, je transmets au TVirtualTreeView la liste des pointeurs du TObjectList et je suppose que lorsque le TVirtualTreeView est détruit il supprime tous les pointeurs contenus dans les noeuds et je me dis que cela doit impacter les pointeurs du TObjectList, je me trompe ?

    A la réflexion oui je me trompe, pour remplir les pointeurs sur les données du TVirtualTreeView on utilise une class et c'est les données de cette classe qui sont supprimées

    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
     
    // Node data record for the the document properties treeview.
     
    PPropertyData = ^TPropertyData;
     TPropertyData = class
        Name : String;         
        ValueType: TValueType;
        Value: WideString;     
        Id : Integer;         
        Changed: Boolean;
        ImageId : Integer;    
        objet : TObject;      // Objet de la liste TObjectList
      end;
     
     
    MonObjet : TObject;
    MaListeObjet : TObjectList;
    PropertyData : TPropertyData;
    Node : PVirtualNode;
     
    ...
     
    VirtualTreeView.NodeDataSize := SizeOf(TPropertyData);
    for i:= 0 to MaListeObjet.count -1 do
    begin
         MonObjet := TObject(MaListeObjet.Items[i]);
     
          PropertyData := TPropertyData.Create;
          PropertyData Name := MonObjet.Nom;
          PropertyData.ValueType := 0;
          PropertyData.objet := MonObjet;
         PropertyData.ImageId :=0 ;
     
         Node := TVirtualTreeView.AddChild(nil, PropertyData);  // On ajoute chaque noeud
    end;
    Donc la liste des objets du TObjectList n'est pas impactée, là je me trompe pas n'est ce pas ?

  4. #4
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 124
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 124
    Par défaut
    La liste n'est pas impactée à la vision du code actuel
    Cependant comme sont libérés les TPropertyData ? j'ai un doute que la libération soit automatique, un évènement OnDeletion comme sur le TTreeView ?

    Le VirtualTreeView alloue et libère les PVirtuaNode incluant la mémoire utilisateur de la taille définie par NodeDataSize
    Mais il ne sait pas libéré un pointeur typé

    Quand tu défini TPropertyData en class, pour lui, c'est 4o en plus, et il va juste libérer les 4o mais en aucun cas appeler un Destroy ou un Dispose si cela avait été un pointeur de record, il n'a qu'un pointeur lambda non typé, il n'a pas la possibilité d'utiliser les RTTI pour finaliser les types record ou string pointés.

    bizarre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    MonObjet := TObject(MaListeObjet.Items[i]);
     PropertyData Name := MonObjet.Nom;
    Tu n'as pas osé redéfinir TObject ?
    MaListeObjet est TObjectList et donc Items[] est TObject, cast curieux


    Un ReportOnMemoryLeak doit indiquer qu'un aucun TPropertyData n'est libéré car seule la consommation mémoire du pointeur en lui l'est !

    En D7, je n'aurais pas eu de scrupule à faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    TPropertyData = packed record // un record non une class
        Name : String[255];         // pas de pointeur que des types simples 
        ValueType: TValueType;
        Value: String[255];  // Cast en WideString ultérieur  
        Id : Integer;         
        Changed: Boolean;
        ImageId : Integer;    
        objet : TObject;      // Objet de la liste TObjectList, weak référence
      end;
    Grace à NodeDataSize l'allocation des PVirtuaNode aurait contenu directement toutes les données sans pointeurs (String étant un pointeur)
    J'évalue SizeOf(TPropertyData) à 256 + 4 + 256 + 4 + 1 + 4 + 4 = 529 (ça dépend la taille de l'enum TValueType et des options de compilation sur la taille minimale des enum)


    En D10, avec l'unicode, le String[255] est un risque de perte de donnée (si l'on travaille dans une application Française et Chinoise en simultané par exemple)
    TPropertyData on le laisse en class
    Par flemme, une TObjectList<TPropertyData> en OwnsObject comme GarbageCollector
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  5. #5
    Membre émérite
    Avatar de free07
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2005
    Messages
    942
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ardèche (Rhône Alpes)

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

    Informations forums :
    Inscription : Mars 2005
    Messages : 942
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    La liste n'est pas impactée à la vision du code actuel
    Cependant comme sont libérés les TPropertyData ? j'ai un doute que la libération soit automatique, un évènement OnDeletion comme sur le TTreeView ?
    C'est avec un Clear du VirtualStringTree, de ce que j'ai pu voir dans le code source, ils font un FreeMem de chaque noeud


    Citation Envoyé par ShaiLeTroll Voir le message
    bizarre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    MonObjet := TObject(MaListeObjet.Items[i]);
     PropertyData Name := MonObjet.Nom;
    Tu n'as pas osé redéfinir TObject ?
    MaListeObjet est TObjectList et donc Items[] est TObject, cast curieux
    Oui en fait j'ai oublié de préciser que c'est TMonObjet qui cast :
    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
    // Node data record for the the document properties treeview.
     
    PPropertyData = ^TPropertyData;
     TPropertyData = class
        Name : String;         
        ValueType: TValueType;
        Value: WideString;     
        Id : Integer;         
        Changed: Boolean;
        ImageId : Integer;    
        objet : TObject;      // Objet de la liste TObjectList
      end;
     
    TMonObjet : class (TObject)
    ...
    end;
     
    MonObjet : TMonObjet;
    MaListeObjet : TObjectList;
    PropertyData : TPropertyData;
    Node : PVirtualNode;
     
    ...
     
    VirtualTreeView.NodeDataSize := SizeOf(TPropertyData);
    for i:= 0 to MaListeObjet.count -1 do
    begin
         MonObjet := TMonObject(MaListeObjet.Items[i]);
     
          PropertyData := TPropertyData.Create;
          PropertyData Name := MonObjet.Nom;
          PropertyData.ValueType := 0;
          PropertyData.objet := MonObjet;
         PropertyData.ImageId :=0 ;
     
         Node := TVirtualTreeView.AddChild(nil, PropertyData);  // On ajoute chaque noeud
    end;
    Citation Envoyé par ShaiLeTroll Voir le message
    Un ReportOnMemoryLeak doit indiquer qu'un aucun TPropertyData n'est libéré car seule la consommation mémoire du pointeur en lui l'est !
    Il faut que je regarde comment utiliser les ReportOnMemoryLeak, j'ai installé la version gratuite de fastMM4

    Citation Envoyé par ShaiLeTroll Voir le message
    En D7, je n'aurais pas eu de scrupule à faire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    TPropertyData = packed record // un record non une class
        Name : String[255];         // pas de pointeur que des types simples 
        ValueType: TValueType;
        Value: String[255];  // Cast en WideString ultérieur  
        Id : Integer;         
        Changed: Boolean;
        ImageId : Integer;    
        objet : TObject;      // Objet de la liste TObjectList, weak référence
      end;
    Grace à NodeDataSize l'allocation des PVirtuaNode aurait contenu directement toutes les données sans pointeurs (String étant un pointeur)
    J'évalue SizeOf(TPropertyData) à 256 + 4 + 256 + 4 + 1 + 4 + 4 = 529 (ça dépend la taille de l'enum TValueType et des options de compilation sur la taille minimale des enum)

    En D10, avec l'unicode, le String[255] est un risque de perte de donnée (si l'on travaille dans une application Française et Chinoise en simultané par exemple)
    TPropertyData on le laisse en class
    Par flemme, une TObjectList<TPropertyData> en OwnsObject comme GarbageCollector
    Sur ce projet, j'utilise Delphi 10.2, merci pour toutes tes précisions !

  6. #6
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 124
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 124
    Par défaut
    Si D10, c'est inclu ReportMemoryLeaksOnShutdown
    RTLMM de D10 est une version simplifie de FastMM4 (euh 4.72 je crois)

    Dans le DPR, je mets ceci, le message de log n'est affiché qu'un Debug sous Delphi

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    {$IFDEF DEBUG}
    {$WARN SYMBOL_PLATFORM OFF}
      System.ReportMemoryLeaksOnShutdown := DebugHook <> 0;
    {$WARN SYMBOL_PLATFORM ON}
    {$ELSE DEBUG}
      System.ReportMemoryLeaksOnShutdown := False;
    {$ENDIF DEBUG}
    Mais si tu as trop de fuite mémoire, si le log dépasse 32Ko, cela échoue à l'affichage donc là faut FastMM4 pour la version fichier du log.



    Sinon, comme je disais le FreeMem libère le PVirtuaNode (soit SizeOf(TVirtuaNode) + NodeDataSize) mais ne libère pas le TPropertyData



    Tu peux aussi écrire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MaListeObjet : TObjectList<TMonObject>;
    Cela évite le cast par la suite
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

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

Discussions similaires

  1. Thread POSIX et gestion mémoire
    Par pier* dans le forum POSIX
    Réponses: 1
    Dernier message: 07/07/2006, 22h36
  2. TAO, Value types et gestion mémoire
    Par TiChabin972 dans le forum CORBA
    Réponses: 1
    Dernier message: 25/04/2006, 21h55
  3. [D7] Tableau dynamique et Gestion mémoire
    Par Cl@udius dans le forum Langage
    Réponses: 7
    Dernier message: 13/03/2006, 16h16
  4. [Gestion mémoire] SetLength sur TDoubleDynArray
    Par MD Software dans le forum Langage
    Réponses: 14
    Dernier message: 24/04/2005, 22h11
  5. Gestion mémoire des Meshes (LPD3DXMESH)
    Par [Hideki] dans le forum DirectX
    Réponses: 1
    Dernier message: 08/07/2003, 21h34

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