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

Langage Delphi Discussion :

create de TObjectList


Sujet :

Langage Delphi

  1. #1
    Membre chevronné
    Avatar de free07
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2005
    Messages
    941
    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 : 941
    Points : 1 946
    Points
    1 946
    Par défaut create de TObjectList
    Bonjour à tous,

    J'ai un phénomène étrange avec le create d'un TObjectList, voici le code :

    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
    TAffaireListe = class(TObjectList)
       private
         fFiltre : TFiltreAffaireListe;
     
       public
         property Filtre : TFiltreAffaireListe read fFiltre write fFiltre;
     
         Constructor Create; overload;
         Destructor Destroy; override;
         ... 
    end;
     
    constructor TAffaireListe.Create;
    begin
      fFiltre := TFiltreAffaireListe.Create;
    end;
     
     
    destructor TAffaireListe.Destroy;
    begin
      if Assigned(fFiltre) then
        FreeAndNil(fFiltre);
     
      inherited; 
    end;
    Cette liste d'objets renseigne un TVirtualStringTree pour l'affichage de cette liste

    Je m'aperçois que l'inherited dans le create a été oublié alors je le rajoute

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    constructor TAffaireListe.Create;
    begin
      inherited Create; 
     
      fFiltre := TFiltreAffaireListe.Create;
    end;
    Mais si je fais cela, cela provoque une violation d'accès lors de l'accès à un élément du TVirtualStringTree ( un élément de ce TObjectList ) et si je ne mets pas l'inherited, tout fonctionne correctement, bizarre non ?

    En tout cas, je n'arrive pas à voir ou est le problème...

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 : 13 563
    Points : 25 165
    Points
    25 165
    Par défaut
    Le constructeur par défaut qui affecte OwnsObjects à True ?
    Le constructeur de TObjectList ne fait rien d'autres, il n'est pas indispensable, il n'y a aucun init de membre interne.

    Je me rends compte à quel point je n'ai pas utilisé de System.Contnrs.TObjectList au profit de System.Generics.Collections.TObjectList<> plus pratique à l'utilisation

    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
    TAffaireListe = class(TObjectList)
       private
         fFiltre : TFiltreAffaireListe;
     
       public
         property Filtre : TFiltreAffaireListe read fFiltre write fFiltre;
     
         Constructor Create(AOwnsObjects: Boolean = False); // pas besoin de overload normalement, le mieux c'est de caché les deux constructeurs ancêtres 
         Destructor Destroy; override;
         ... 
    end;
     
    constructor TAffaireListe.Create(AOwnsObjects: Boolean = False);
    begin
      inherited Create(AOwnsObjects); 
     
      fFiltre := TFiltreAffaireListe.Create;
    end;
     
     
    destructor TAffaireListe.Destroy;
    begin
      FreeAndNil(fFiltre);
     
      inherited Destroy(); 
    end;

  3. #3
    Membre chevronné
    Avatar de free07
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2005
    Messages
    941
    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 : 941
    Points : 1 946
    Points
    1 946
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Le constructeur par défaut qui affecte OwnsObjects à True ?
    Le constructeur de TObjectList ne fait rien d'autres, il n'est pas indispensable, il n'y a aucun init de membre interne.
    Effectivement, le problème est bien là.

    Cela veut donc dire qu'à un moment du programme, cette liste est détruite alors qu'elle ne devrait pas l'être. Et que pour l'instant tout va bien car la liste des objets n'est pas supprimée...

    Bon, il reste plus qu'à découvrir où cette liste est supprimée !

  4. #4
    Membre émérite
    Avatar de ALWEBER
    Homme Profil pro
    Expert Delphi
    Inscrit en
    Mars 2006
    Messages
    1 504
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Expert Delphi

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 504
    Points : 2 773
    Points
    2 773
    Billets dans le blog
    10
    Par défaut
    Pourquoi "Constructor Create; overload;" ?

  5. #5
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 : 13 563
    Points : 25 165
    Points
    25 165
    Par défaut
    Citation Envoyé par ALWEBER Voir le message
    Pourquoi "Constructor Create; overload;" ?
    On peut penser que cela a été copier-coller de l'ancêtre qui a deux constructeurs, celui par défaut, celui avec AOwnsObjects
    Rien n'est plus simple que s'inspirer d'un code existant

    Citation Envoyé par free07 Voir le message
    Bon, il reste plus qu'à découvrir où cette liste est supprimée !
    Il est fréquent de libérer une liste après l'avoir utiliser, pensant qu'elle n'est plus utile, les objets ayant été confié à un autre objet
    Tout dépend comme tu conçois ton programme mais mettre OwnsObjects à False et une liste à durée de vie limitée, c'est quelques dizaines d'octets en moins de consommé

    Et faudra voir aussi si le VirtualTreeView libère les objets dans un OnDeletion par exemple

  6. #6
    Membre chevronné
    Avatar de free07
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2005
    Messages
    941
    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 : 941
    Points : 1 946
    Points
    1 946
    Par défaut
    Citation Envoyé par ALWEBER Voir le message
    Pourquoi "Constructor Create; overload;" ?
    Citation Envoyé par ShaiLeTroll Voir le message
    On peut penser que cela a été copier-coller de l'ancêtre qui a deux constructeurs, celui par défaut, celui avec AOwnsObjects
    Rien n'est plus simple que s'inspirer d'un code existant
    Je suppose aussi mais je ne peux pas le confirmer car c un prg dont j'ai repris la maintenance et les auteurs ne sont plus joignables
    En tout cas, rajouter "inherited Create" n'a pas été vain car cela m'a permis de mettre le doigt sur ce problème de gestion mémoire.

    Citation Envoyé par ShaiLeTroll Voir le message
    Il est fréquent de libérer une liste après l'avoir utiliser, pensant qu'elle n'est plus utile, les objets ayant été confié à un autre objet
    Tout dépend comme tu conçois ton programme mais mettre OwnsObjects à False et une liste à durée de vie limitée, c'est quelques dizaines d'octets en moins de consommé

    Et faudra voir aussi si le VirtualTreeView libère les objets dans un OnDeletion par exemple
    Merci pour ces remarques.

  7. #7
    Membre chevronné
    Avatar de free07
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2005
    Messages
    941
    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 : 941
    Points : 1 946
    Points
    1 946
    Par défaut
    Bonjour,


    Citation Envoyé par ShaiLeTroll Voir le message

    Il est fréquent de libérer une liste après l'avoir utiliser, pensant qu'elle n'est plus utile, les objets ayant été confié à un autre objet
    Tout dépend comme tu conçois ton programme mais mettre OwnsObjects à False et une liste à durée de vie limitée, c'est quelques dizaines d'octets en moins de consommé
    Je galère pour retrouver ce problème de gestion mémoire . Est ce que quelqu'un a une astuce pour retrouver un objet libéré et qui n'aurait pas du l'être ? Y a t'il une méthode efficace pour mettre le doigt sur le code en question ?

  8. #8
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    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 : 13 563
    Points : 25 165
    Points
    25 165
    Par défaut
    Si cela concerne TAffaireListe, met un point d'arrêt dans le Destroy et regarde la Pile d'appel, ça te donnera une idée du mauvais chemin
    Si c'est un autre objet, ajoute un destructeur si tu le peux et même technique pour observe la Pile d'Appel

    L'exception étant à l'utilisation, elle est rarement l'endroit coupable
    Utiliser du FreeAndNil le plus souvent que possible aussi avec une certain paranoïa de if Assigned() then.

    Je suppose que tu es resté inherited Create(); car la TAffaireListe doit avoir une vie plus longue que celle du TreeView et qu'elle doit rester responsable des objets qu'elle contient
    Si la liste n'est pas prévu pour durer, n'hésite pas comme proposer plus haut inherited Create(AOwnsObjects); ou plus simplement inherited Create(False);

  9. #9
    Membre chevronné
    Avatar de free07
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2005
    Messages
    941
    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 : 941
    Points : 1 946
    Points
    1 946
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Si cela concerne TAffaireListe, met un point d'arrêt dans le Destroy et regarde la Pile d'appel, ça te donnera une idée du mauvais chemin
    Si c'est un autre objet, ajoute un destructeur si tu le peux et même technique pour observe la Pile d'Appel

    L'exception étant à l'utilisation, elle est rarement l'endroit coupable

    Utiliser du FreeAndNil le plus souvent que possible aussi avec une certain paranoïa de if Assigned() then.
    C'est ce que j'ai fait sans succès.
    TAffaireList est déclaré en public dans un frame qui est appelé par pas mal de fiches et d'autres frames, c'est un peu le foutoir je trouve mais bon faut que je fasse avec, pas le temps ( et le budget ) pour refaire toute cette partie.
    Le plantage se situe au niveau de l'accès au noeud du VirtualTreeView qui a été alimenté par le TAffaireList ( TObjectList ) de ce que je me souviens, le VirtualTreeView ne mémorise pas les données mais simplement les pointeurs de la liste. Donc je n'ai pas tord en soupçonnant un problème lié à la gestion de TAffaireList ?

    Ca plante à ce moment là :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
      ...  
      Noeud := VSTListeAffairesClient.GetFirstSelected;
      NoeudModification := Noeud; // On le passe à la frame pour utilisation dans le formulaire même lorsqu'il n'est plus sélectionné
      if Assigned(Noeud) then
      begin
         l_Donnees := VSTListeAffairesClient.GetNodeData(Noeud);
         if Assigned(l_Donnees) and Assigned(l_Donnees.Objet) then
         begin
            if (l_Donnees.Objet is TAffaire) then -------> BOUM : VA !
           ... 
         ...
    En fait c'est pas vraiment dans le TListAffaire mais l'objet mémorisé par le pointeur Objet utilisé dans le VirtualTreeView qui mémorise le pointeur d'un élément de la TListAffaire et si je mets inherited, cet élément n'existe plus à un moment donné mais j'arrive pas à voir à que moment cette liste est détruite lors du plantage ou alors mon raisonnement est à côté de la plaque !

    Un 1er appel est fait une première fois après le remplissage du VirtualTreeView : ça passe
    puis ça plante lorsqu'on fait un autre appel pour actualiser les données, le problème se situe entre ces deux moments...

    Désolé si je réfléchis à haute voix Mais faut que je m'y replonge...
    Citation Envoyé par ShaiLeTroll Voir le message
    Je suppose que tu es resté inherited Create(); car la TAffaireListe doit avoir une vie plus longue que celle du TreeView et qu'elle doit rester responsable des objets qu'elle contient
    Si la liste n'est pas prévu pour durer, n'hésite pas comme proposer plus haut inherited Create(AOwnsObjects); ou plus simplement inherited Create(False);
    Oui, le TAffaireList a une durée de vie plus longue.

  10. #10
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 871
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 871
    Points : 11 361
    Points
    11 361
    Billets dans le blog
    6
    Par défaut
    Bonsoir,
    Quelques questions pour faire avancer le schmilblick :
    Que fait le TAffaireList.Destroy ? A-t-il été modifié en parallèle du Create ?
    Si le filtre sert à modifier les éléments présentés de la liste, y a-t-il une liste totale interne et celle présentée, ou la liste globale est-elle modifiée ?
    Le code appelle-t-il quelque part TAffaireList.Clear ?

  11. #11
    Membre expérimenté Avatar de guillemouze
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    876
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Novembre 2004
    Messages : 876
    Points : 1 448
    Points
    1 448
    Par défaut
    Citation Envoyé par free07 Voir le message
    Est ce que quelqu'un a une astuce pour retrouver un objet libéré et qui n'aurait pas du l'être ? Y a t'il une méthode efficace pour mettre le doigt sur le code en question ?
    Comme le dit Shai, il faut déjà cibler qui détruit ton objet (si tu estimes qu'il doit être possédé par TAffaireListe, et ne doit donc pas être détruit en dehors).
    Ma petite technique pour ne pas m’arrêter quand c'est un destructeur normal c'est de faire des groupes de points d’arrêt:
    met un point d’arrêt dans TAffaire.Destroy, puis fais un clic-droit dessus > propriétés du point d’arrêt, et dans groupe, tu met qqchose (disons "fuite").
    Ensuite, pour ne pas qu'il s’arrête lors des destroy de ta liste, mets des points d’arrêt dans le destroy de la liste, mais cette fois ci il faut [des]activer le groupe "fuite" dans les propriétés avancées du pt d’arrêt (et décocher "arrêter")
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    destructor TAffaireListe.Destroy;
    begin
      FreeAndNil(fFiltre);<- activer le groupe
     
      inherited Destroy(); 
    end; <- desactiver le groupe
    Il faudra peut être aussi le faire sur le clear (ou même mieux, surcharge la méthode notify dans TAffaireListe).

    Un autre cas qui peut destroy ton affaire, c'est MonAffaireListe[i] := UneAutreAffaire; qui va détruire l'objet qui était à cet indice.

  12. #12
    Membre chevronné
    Avatar de free07
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2005
    Messages
    941
    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 : 941
    Points : 1 946
    Points
    1 946
    Par défaut
    Bonjour

    Citation Envoyé par tourlourou Voir le message
    Bonsoir,
    Quelques questions pour faire avancer le schmilblick :
    Que fait le TAffaireList.Destroy ? A-t-il été modifié en parallèle du Create ?
    Oui, je l'ai aussi modifié en rajoutant le inherited qui n'y été pas aussi
    Je ne comprend pas cette façon de faire : utiliser TObjectList sans se soucier de la libération mémoire. D'autant plus que les listes sont créées à plusieurs endroits dans le programme pour différentes fiches et frames.

    Citation Envoyé par tourlourou Voir le message
    Si le filtre sert à modifier les éléments présentés de la liste, y a-t-il une liste totale interne et celle présentée, ou la liste globale est-elle modifiée ?
    Non le filtre est utilisé pour modifier la liste globale, il n'y a pas de différence entre la liste créée et celle affichée.
    D'ailleurs à chaque fois que l'utilisateur lance une recherche, ils créaient une nouvelle liste sans supprimer la précédente !


    Citation Envoyé par tourlourou Voir le message
    Le code appelle-t-il quelque part TAffaireList.Clear ?
    Oui, il y avait effectivement un Clear qui aurait pu expliquer le problème mais ce n'est malheureusement pas le cas. Je l'ai mis en commentaire mais cela plante toujours au même endroit...

    Ce problème va me prendre beaucoup de temps mais je crois que cela est nécessaire afin de rendre le programme plus robuste et surtout éliminer les nombreuses fuites mémoire que j'ai trouvé en mettant en place FastMM4.

  13. #13
    Membre chevronné
    Avatar de free07
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2005
    Messages
    941
    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 : 941
    Points : 1 946
    Points
    1 946
    Par défaut
    Citation Envoyé par guillemouze Voir le message
    Il faudra peut être aussi le faire sur le clear (ou même mieux, surcharge la méthode notify dans TAffaireListe).

    Un autre cas qui peut destroy ton affaire, c'est MonAffaireListe[i] := UneAutreAffaire; qui va détruire l'objet qui était à cet indice.
    Bonne idée, merci. Je vais vérifier tout ça !

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

Discussions similaires

  1. Parent et Create
    Par Arrown dans le forum Composants VCL
    Réponses: 4
    Dernier message: 09/10/2003, 11h13
  2. Database new user & create table
    Par MFDev dans le forum InterBase
    Réponses: 3
    Dernier message: 30/09/2003, 20h47
  3. unable to create INITIAL extent for segment in tablespace
    Par Ludolitaliano dans le forum Administration
    Réponses: 4
    Dernier message: 11/09/2003, 16h43
  4. Propriété tableau et TObjectList
    Par Mouss26 dans le forum Langage
    Réponses: 3
    Dernier message: 07/03/2003, 14h32
  5. TXMLModule.create - name = resource not found
    Par pram dans le forum XMLRAD
    Réponses: 2
    Dernier message: 04/03/2003, 10h54

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