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 :

Court circuiter le ref-count d'un TInterfacedObject!


Sujet :

Langage Delphi

  1. #1
    Membre actif Avatar de Suryavarman
    Homme Profil pro
    Développeur 3D
    Inscrit en
    Mai 2006
    Messages
    233
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur 3D
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Mai 2006
    Messages : 233
    Points : 245
    Points
    245
    Par défaut Court circuiter le ref-count d'un TInterfacedObject!
    Ceux qui utilisent les interfaces avec des objets dérivant de TinterfacedObject
    peuvent ainsi apprécier le ref-count ou pas .

    Imaginons que nous soignons dans un arbre. L'un des parents de cet arbre est manipulé par le biais d'une interface lors d'un traitement et possède une référence stockée dans ses enfants sous forme d'interface. Imaginons que ce parent se retrouve ne plus être utilisé par ses parents et par le programme, il devrait se libérer automatiquement. Sauf que ses enfants continuent à garder une référence de lui. Là vous avez une fuite mémoire. Pour ce faire il serait bien d'avoir un objet qui puisse stocker une interface sans pour autant incrémenter le ref-count de l'objet qui est stocké( référence faible comme dans le controller des TAggregatedObject). Pour ce faire je propose ceci :
    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
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    unit interf_InterfaceFaible;
     
    interface
     
    type
      // l'interface faible permet de stocker une interface sans la notion de ref count ( idéal pour éliminer les références circulaires
      // Attention ne pas faire IInterface(aInterfaceFaible)  mais aInterface := aInterfaceFaible ;
      // aInterfaceFaible := aInterface ; Rq: IInterfaceFaible(aInterface) fonctionne mais je vois pas à quoi ça peut servir
      // une fonction demandant en paramètre une IInterface ne peut recevoir directement un IInterfaceFaible il faut le convertir avant
      // le support à été surchargé exprès support( aInterfaceFaible, ITruc, aTruc ) ;
      // aInterfaceFaible := function_retournent_une_IInterface() ;à ne pas faire.
     
      IInterfaceFaible = record
        private
           FInterface: Pointer;
     
           procedure SetInterface( aInterface : IInterface ) ;
           function GetInterface() : IInterface ;
     
           property m_Interface : IInterface read GetInterface write SetInterface ;
        public
     
          class operator Implicit( a : IInterface ) : IInterfaceFaible ; overload;
          class operator Implicit( a : IInterfaceFaible ) : IInterface ; overload; 
     
      end;
     
      function Supports(const Instance: IInterfaceFaible; const IID: TGUID; out Intf): Boolean; overload;
     
    implementation
     
    function Supports(const Instance: IInterfaceFaible; const IID: TGUID; out Intf): Boolean;
    var aInt : IInterface ;
     
    begin
     
      aInt := Instance ;
      Result := (aInt <> nil) and (aInt.QueryInterface(IID, Intf) = 0);
     
    end;
    ////////////////////////////
     
     
    { IInterfaceFaible }
     
    function IInterfaceFaible.GetInterface: IInterface;
    begin
     
      result := IInterface(FInterface) ;
     
    end;
    ////////////////////////////
     
    procedure IInterfaceFaible.SetInterface(aInterface: IInterface);
    begin
     
      FInterface := Pointer(aInterface) ;
     
    end;
    ////////////////////////////
     
    class operator IInterfaceFaible.Implicit( a : IInterface ) : IInterfaceFaible ;
    var  aIntfFaible : IInterfaceFaible ;
     
    begin
     
      aIntfFaible.m_Interface := a ;
     
      result := aIntfFaible ;
     
    end;
    ////////////////////////////
     
    class operator IInterfaceFaible.Implicit( a : IInterfaceFaible ) : IInterface ;
    begin
     
      result := a.m_Interface ;
     
    end;
    ////////////////////////////
     
     
    end.
    Exemple d'utilisation :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var  aTest : IInterfaceFaible ;
         aInt  : ITruc ;
     
    begin
     
      aInt := TTruc.Create ;
      aTest := aInt ;
      aInt := nil ; // la ça se libère car  aTest est une référence faible
     
     
    end;
    J'ai voulu que ça soit asse transparent qu'on est pas à créer cet objet où d'avoir un Pointer qui se balade alors qu'il contient une interface.
    Voila je voulais vous en faire part et avoir votre avis sur cette méthode .

    (l'implements n'a cas bien se tenir )
    "Quand le monde est dangereux, l'humilité est un facteur de longévité." ( Baxter "Evolution" )

  2. #2
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 445
    Points
    28 445
    Par défaut
    ben je vois pas trop l'intéret de garder une référence à une interface détruite...mais bon si tu y tiens

    par contre je vois que tu utilises des extensions du langage indisponible sous Delphi 6

    tu peux m'éclairer sur la signification du "class operator Implicit"

    si je comprend bien ça correspond à l'opérateur ":=" dans un sens ou dans l'autre.

    et qu'est ce que ça donne si j'ajoute ceci, qui n'a à priori pas de sens ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
          class operator Implicit( a : integer) : string ; overload;
    et pour n'avoir pas écrit ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    class operator IInterfaceFaible.Implicit( a : IInterface ) : IInterfaceFaible ;
    //var  aIntfFaible : IInterfaceFaible ;
     
    begin
     
      {aIntfFaible}Result.m_Interface := a ;
     
    //  result := aIntfFaible ;
     
    end;
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  3. #3
    Membre actif Avatar de Suryavarman
    Homme Profil pro
    Développeur 3D
    Inscrit en
    Mai 2006
    Messages
    233
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur 3D
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Mai 2006
    Messages : 233
    Points : 245
    Points
    245
    Par défaut
    Result.m_Interface := a ;
    J'avais pas penser à ça :p Mici

    et qu'est ce que ça donne si j'ajoute ceci, qui n'a à priori pas de sens ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
          class operator Implicit( a : integer) : string ; overload;
    Je sais pas essai .

    Implicit (il y aussi explicite mais j'ai pas vu la différence dans l'utilisation )
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    a :  integer ;
    b :  long ;
     
    a := b ; // b est implicitement casté en un entier
    a := a + b ;
    "Quand le monde est dangereux, l'humilité est un facteur de longévité." ( Baxter "Evolution" )

  4. #4
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 445
    Points
    28 445
    Par défaut
    Citation Envoyé par Suryavarman Voir le message
    Je sais pas essai .
    ça n'existe pas sous Delphi 6...

    Citation Envoyé par Suryavarman Voir le message
    Implicit (il y aussi explicite mais j'ai pas vu la différence dans l'utilisation )
    ok, laisse tomber
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  5. #5
    Membre actif Avatar de Suryavarman
    Homme Profil pro
    Développeur 3D
    Inscrit en
    Mai 2006
    Messages
    233
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur 3D
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Mai 2006
    Messages : 233
    Points : 245
    Points
    245
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    class operator Implicit( a : integer) : string ; overload;
    ça fonctionnera pas car il te faut un des deux paramètres correspondant à la classe/structure surchargé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
    19
    20
    21
    22
    23
    24
    //Voici quelques exemples d'opérateurs surchargés : 
     
    type
       TMyClass = class
         class operator Add(a, b: TMyClass): TMyClass;      // Ajout de deux opérandes de type TMyClass
         class operator Subtract(a, b: TMyClass): TMyclass; // Soustraction de type TMyClass
         class operator Implicit(a: Integer): TMyClass;     // Conversion implicite d'un entier en type TMyClass
         class operator Implicit(a: TMyClass): Integer;     // Conversion implicite de TMyClass en Integer
         class operator Explicit(a: Double): TMyClass;     // Conversion explicite d'un double en type TMyClass
       end;
     
    // Exemple d'implémentation de Add
    class operator TMyClass.Add(a, b: TMyClass): TMyClass;
    begin
       // ...
    end;
     
    var
    x, y: TMyClass;
    begin
       x := 12;      // Conversion implicite à partir d'un Integer
       y := x + x;   // Appelle TMyClass.Add(a, b: TMyClass): TMyClass
       b := b + 100; // Appelle TMyClass.Add(b, TMyClass.Implicit(100))
    end;
    "Quand le monde est dangereux, l'humilité est un facteur de longévité." ( Baxter "Evolution" )

  6. #6
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 468
    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 468
    Points : 24 896
    Points
    24 896
    Par défaut
    Citation Envoyé par Suryavarman Voir le message
    . Sauf que ses enfants continuent à garder une référence de lui. Là vous avez une fuite mémoire. Pour ce faire il serait bien d'avoir un objet qui puisse stocker une interface
    Ce n'est pas une fuite mémoire, puisque lorsque le dernier enfant sera libérer, le parent le sera aussi, c'est plutôt de le consommation non-utile, qu'une fuite non ?
    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

  7. #7
    Membre actif Avatar de Suryavarman
    Homme Profil pro
    Développeur 3D
    Inscrit en
    Mai 2006
    Messages
    233
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur 3D
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Mai 2006
    Messages : 233
    Points : 245
    Points
    245
    Par défaut
    Le parent est celui qui possède les références vers ses enfants. C'est un arbre , quand tu coupes une branche elle disparait de l'arbre, donc automatiquement quand le parent n'est plus utilisé tout ce qu'il possède doit le suivre dans ça chute.
    "Quand le monde est dangereux, l'humilité est un facteur de longévité." ( Baxter "Evolution" )

  8. #8
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 468
    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 468
    Points : 24 896
    Points
    24 896
    Par défaut
    Donc où est la fuite ?
    Puisque si le on utilise plus le parent, ce dernier libère ses petits ... sauf si tu as gardé une interface connecté sur un enfant qu'il ne faut pas libérer (justement le refCount doit être vérifié), le parent du coup de ne l'est pas non plus, ...
    Je ne suis pas en forme aujourd'hui, donc si cela se trouve, c'est très simple cette histoire, mais là, je ne vois pas !
    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

  9. #9
    Membre actif Avatar de Suryavarman
    Homme Profil pro
    Développeur 3D
    Inscrit en
    Mai 2006
    Messages
    233
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur 3D
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Mai 2006
    Messages : 233
    Points : 245
    Points
    245
    Par défaut
    sauf si tu as gardé une interface connecté sur un enfant qu'il ne faut pas libérer (justement le refCount doit être vérifié), le parent du coup de ne l'est pas non plus, ...
    Vi c'est bien ça le soucis et manipuler le ref-count est comment dire...casse gueule et laid .
    "Quand le monde est dangereux, l'humilité est un facteur de longévité." ( Baxter "Evolution" )

  10. #10
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 468
    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 468
    Points : 24 896
    Points
    24 896
    Par défaut
    Il faudrait que la parent ne manipule ses enfants que via Interface même du côté implémentation, ainsi, le parent met à nil sa liste de petits, ... et avant de les mettre à nil, il les notify de sa disparition, ainsi les enfants mettent à nil l'interface de leur parent, ... bon c'est pas clair mais en ne jouant qu'avec les interfaces on peut y arriver sans bidouiller la lib, et surtout cela fonctionnerait même avec un vieux Delphi ... et du coup, on rend possible l'extraction d'une branche en plein milieu et en libérant le reste ...
    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

  11. #11
    Membre actif Avatar de Suryavarman
    Homme Profil pro
    Développeur 3D
    Inscrit en
    Mai 2006
    Messages
    233
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur 3D
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Mai 2006
    Messages : 233
    Points : 245
    Points
    245
    Par défaut
    Mon_Interface_Avec_Refcount := nil ;

    Mon_Objet_Sans_RefCount.Free ;

    L'intérêt c'est justement que la libération soit automatisé.
    "Quand le monde est dangereux, l'humilité est un facteur de longévité." ( Baxter "Evolution" )

  12. #12
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 468
    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 468
    Points : 24 896
    Points
    24 896
    Par défaut
    Hein ?

    Je te proposais une méthode qui permet de bénéficier du TInterfacedObject sans avoir à tout refaire, juste en pensant totalement interface entre tes objets sans utiliser les objets d'implémentation en direct ... et surtout en ne bidouillant la lib avec un record et du pointeur

    Donc ce problème que tu soulèves m'intéresse avec mes connaissances des interfaces, je le vois simplement, comme ceci, et justement si je me trompe, j'aimerais le savoir ... ça pourrait m'être utile ...

    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
    type
      INode = interface
        ...
        function GetEnfant(Index: Integer): IEnfant;
        procedure SetEnfant(Index: Integer; Value: IEnfant);
        property Parent: IParent read ...;
        property Enfants[Index: Integer]: IEnfant read GetEnfant write SetEnfant;
        ...
      end;  
     
      TNodeImpl = class(TInterfacedObject, INode)
      private
        FParent: IParent;
        procedure SetParent(Value: IParent);
        FEnfants: array of IEnfant;
        function GetEnfant(Index: Integer): IEnfant;
        procedure SetEnfant(Index: Integer; Value: IEnfant);
      public
        property Enfants[Index: Integer]: IEnfant read GetEnfant write SetEnfant;
        destructor Destroy(); override;
      end;

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    destructor TNodeImpl.Destroy(); 
    begin
      FParent := nil; // Je me libère, donc mon parent apparait une fois de moins // RefCount Parent - 1;
     
      for I := Low(FEnfants) to High(FEnfants) do
        FEnfants := nil; // RefCount Enfant - 1; // et par logique, le parent qui était autant de fois appelé est libéré ...
     
      inherited;
    end;
     
    procedure TEnfantImpl.SetParent(Value: IParent);
    begin
      FParent := Value; // RefCount Parent + 1; // Euh, du moins j'espère, sinon tout tombe à l'eau ...
    end;
    Normalement, tu libére le parent via une mise à nil dans l'objet "client", mais cet objet garde une instance d'un enfant, donc il faut garder celui-ci et sa descendance car il est peut-être lui même un parent ...
    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

  13. #13
    Membre actif Avatar de Suryavarman
    Homme Profil pro
    Développeur 3D
    Inscrit en
    Mai 2006
    Messages
    233
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur 3D
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Mai 2006
    Messages : 233
    Points : 245
    Points
    245
    Par défaut
    Humm relie le premier poste quand tu seras reposé.
    J'ai pas modifier la lib.

    Et c'est transparent, à la différence de l'affectation d'un nil.(si dans l'exemple j'ai mis nil c'est pour illustrer son fonctionnement ).

    Je comprend bien ce que tu proposes. Mais ça fonctionne pas. Le parent doit prendre la décision de se libérer et pour cela, plus personne ne doit le référencer même ses enfants. Dans ce que tu proposes, il n'informera jamais ses enfants de sa libération car il se libérera jamais t'en que ses enfants auront une référence de lui avec ce lien fort du ref_counting. J'ai rajouter juste une notion de lien faible. Au lieu de mettre des trucs à nil de partout ( au final tu seras obligé d'allé bidouiller le ref_count) tu as juste à mettre un lien faible entre l'enfant et le parent et le tour est joué et tout se libère.
    EDIT:

    ATTEND JE VIENS DE VOIR TON EDIT JE LIS . :p

    EDIT:
    C'est bon j'ai lu.

    Ton objet client mettra à nil le root , tu n'auras plus de pointeur sur lui mais lui à encore ses enfants qui pointe vers lui, il ne va donc pas se libérer et toi tu auras un arbre à la dérive dans la mémoire :p .

    pour qu'il se libère il faudrait que son conteur soit à un ( tout du moi si il n'y a que le client qui le référence ) pour cela les enfants doivent avoir un lien faible qui n'incrémente pas le ref-count du parent. Et cet fois magie le parent se libère, la liste qui les contient qui est une interface se libère, les enfants n'étant plus possédé par la liste , se libèrent et ainsi de suite. Aucun nil rien juste une référence faible de l'enfant vers le parent.
    "Quand le monde est dangereux, l'humilité est un facteur de longévité." ( Baxter "Evolution" )

  14. #14
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 468
    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 468
    Points : 24 896
    Points
    24 896
    Par défaut
    Je pense que j'ai modifié mon post après ton message (j'ai mis du pseudo code), ... bon en fait, selon ma vision des interfaces je ne vois pas la fuite mémoire, surement que je n'ai pas les idées claires ...

    quand je dis modifié la lib, c'est dans le sens, que tu réinvente un type qui existe déjà (du moins j'ai cette impression ou alors que tu cherches une solution tordue pour corriger une erreur de conception), que du fait que tu sois en Delphi 200x, tu utilise un record comme une classe, et ce n'est pas de ta faute, mais celle de borland, ce qui est pour moi une des abérrations de Delphi.NET qui dénature complétement le pascal est faisant passer les structures pour des pseudo objet ... et que du coup, en fait on ne parle plus tous les deux de la mêem façon, mais je pense en Delphi 6 et toi en Delphi 2006, il y a juste 10 ans de techno qui nous sépare, je suis techniquement vieillo à 26 ans ... c'est con non ?
    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

  15. #15
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 468
    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 468
    Points : 24 896
    Points
    24 896
    Par défaut
    Complexe de se suivre en message via EDIT interposé ! non ?

    Bon, en fait, j'avais écrit un truc qui j'ai par la suite supprimé me disant qu'il y avait redondance, pour les objets normaux oui, pour les objets en refcount non ... bon en plus c'était faux au niveau du tableau, ...

    EDIT
    voir plus loin ... le bon destructeur
    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

  16. #16
    Membre actif Avatar de Suryavarman
    Homme Profil pro
    Développeur 3D
    Inscrit en
    Mai 2006
    Messages
    233
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur 3D
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Mai 2006
    Messages : 233
    Points : 245
    Points
    245
    Par défaut
    j'ai Delphi 2007.

    Pour la structure je suis pas d'accord la voir comme un objet c'est plus proche de la notion qu'elle dégage. C'est un objet épuré sans héritage ni interface mais avec des procédures des fonctions des propriétées etc etc. ( quand j'ai vue C les structure j'ai demandé au prof : "Mr, je croyais que le c ne faisait pas d'objet".

    Mais que tu sois en delphi ancien ou pas tu es confronté au même soucis.

    et pour les anciennes versions il suffit de stocker dans un pointer l'interface pour avoir une référence faible, mais ça demande de savoir sur quoi on travail.
    "Quand le monde est dangereux, l'humilité est un facteur de longévité." ( Baxter "Evolution" )

  17. #17
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 468
    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 468
    Points : 24 896
    Points
    24 896
    Par défaut
    Citation Envoyé par Suryavarman Voir le message
    Pour la structure je suis pas d'accord la voir comme un objet c'est plus proche de la notion qu'elle dégage. C'est un objet épuré sans héritage ni interface mais avec des procédures des fonctions des propriétées
    ce n'est plus une structure, ... c'est un objet à moitié fini, autant faire un objet ...bon, euh, ce n'est pas le sujet, mais ayant commencé par apprendre le C, ... les structures ont un intéret lié à la mémoire en particulier pour l'échange de données avec des machines (là c'est le métier qui parle) et les objets c'est plus pour la partie traitement, d'ailleurs, certains de mes objets ne sont que des enveloppes autour d'une structure ... ce n'est pas le sujet, revenons à nos moutons ...

    Qe penses-tu de ce destructeur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    destructor TNodeImpl.Destroy(); 
    begin
      FParent := nil; // Je me libère, donc mon parent apparait une fois de moins // RefCount Parent - 1;
     
      for I := Low(FEnfants) to High(FEnfants) do
      begin
        FEnfants[i].Parents := nil; // ben oui, tous les enfants qui était attaché devienent les racines d'une multitude d'arbre, et seuls ceux ayant une interface dans l'objet "client" survivront ... 
        FEnfants[i] := nil; // RefCount Enfant - 1; // si c'était la dernier instance, la ligne du dessus est redondant puisque le destroy met le parent à nil, mais si ce n'est pas la dernière, l'enfant survit à son parent et l'enfant l'oubli ...  
      end;
     
      inherited;
    end;
    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

  18. #18
    Membre actif Avatar de Suryavarman
    Homme Profil pro
    Développeur 3D
    Inscrit en
    Mai 2006
    Messages
    233
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur 3D
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Mai 2006
    Messages : 233
    Points : 245
    Points
    245
    Par défaut
    Bein il fonctionne bien, mais faudrait encore qu'il soit appelé. Le problème c'est le point d'entrée. T'en que ton parent aura un ref-count différent de zéro tu ne rentrera jamais dans ton destroy.

    Pour la structure et l'objet...pourquoi j'ai pris une structure et non un objet ?

    ->La structure n'a pas besoin de se construire elle est statique. Ce qui permet d'avoir un comportement qui donne l'illusion d'avoir un pointeur d'interface.
    "Quand le monde est dangereux, l'humilité est un facteur de longévité." ( Baxter "Evolution" )

  19. #19
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 468
    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 468
    Points : 24 896
    Points
    24 896
    Par défaut
    Citation Envoyé par Suryavarman Voir le message
    Bein il fonctionne bien, mais faudrait encore qu'il soit appelé. Le problème c'est le point d'entrée. T'en que ton parent aura un ref-count différent de zéro tu ne rentrera jamais dans ton destroy.
    Merci, voilà, encore je confond objet normaux et objet ref count, c'est pas vrai !!!

    effectivement, il faut donc ajouter une méthode à l'interface !!!

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    INode = interface
        ...
        procedure Delete();
        ...
      end;
    et le Delete contient le code du Destructeur ... oh, mince alors, c'est exactement le principe du TTreeNodes\TTreeNode ... le Delete d'un Node c'est sa libération, lol, les gars de borland y avait pensé avant nous

    Issu de Delphi 6 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    procedure TTreeNodes.Delete(Node: TTreeNode);
    begin
      Node.Delete;
    end;
     
    procedure TTreeNode.Delete;
    begin
      if not Deleting then
        Free;
    end;
    Avec ceci, ça passe ... et en plus c'est logique, récursif, c'est tout à fait un arbre ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    procedure TNodeImpl.Delete(); 
    begin
      FParent := nil; 
     
      for I := Low(FEnfants) to High(FEnfants) do
      begin
        FEnfants[I].Delete(); 
        FEnfants[I] := nil;
      end;
    end;
    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

  20. #20
    Membre actif Avatar de Suryavarman
    Homme Profil pro
    Développeur 3D
    Inscrit en
    Mai 2006
    Messages
    233
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur 3D
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Mai 2006
    Messages : 233
    Points : 245
    Points
    245
    Par défaut
    ...

    Euh oui ça marche mais pourquoi utilises tu une interface alors ?
    Que va t'il se passer si un guss décide de pas faire delete car il se dit c'est une interface elle va se libérer toute seul .
    "Quand le monde est dangereux, l'humilité est un facteur de longévité." ( Baxter "Evolution" )

Discussions similaires

  1. [PageControl] Raccourcis claviers court-circuités
    Par Manopower dans le forum Composants VCL
    Réponses: 8
    Dernier message: 04/09/2009, 16h52
  2. [Disque Dur] Problème de court-circuit
    Par saih_tam dans le forum Composants
    Réponses: 9
    Dernier message: 20/05/2009, 15h03
  3. Réponses: 2
    Dernier message: 06/07/2007, 10h41
  4. Réponses: 13
    Dernier message: 09/04/2007, 13h20
  5. Réponses: 4
    Dernier message: 16/03/2004, 18h03

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