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

Delphi Discussion :

Libération de composants


Sujet :

Delphi

  1. #1
    Invité
    Invité(e)
    Par défaut Libération de composants
    Bonjour,

    Je suis tombé sur cette page du wiki.
    Ils donnent le code suivant :
    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
    procedure TForm1.FormCreate(Sender: TObject);
    var
      TaskDialog: TTaskDialog;
      Button: TTaskDialogBaseButtonItem;
    begin
      // display a task message dialog at a certain position
      TaskMessageDlgPos('Continue', 'Are you sure you want to continue?', mtWarning, mbYesNoCancel, 0, 10, 10);
     
      // display another message dialog at the current position
      TaskMessageDlg('Error', 'An error has occured', mtError, mbAbortRetryIgnore, 0);
     
      // create a custom task dialog
      TaskDialog := TTaskDialog.Create(Self);
      TaskDialog.Title := 'An error has occured in the query.';
      TaskDialog.Caption := 'Query result';
     
      // assign a MB_OK modal result to the task dialog
      TaskDialog.ModalResult := MB_OK;
     
      // add some customized buttons to the task dialog
      Button := TaskDialog.Buttons.Add;
      Button.Caption := 'Continue';
      Button.ModalResult := MB_OK;
     
      Button := TaskDialog.Buttons.Add;
      Button.Caption := 'Retry';
      Button.ModalResult := MB_RETRYCANCEL;
     
      // display the dialog box
      TaskDialog.Execute;
    end;
    Il n'y a pas de libération du TTaskDialog à la fin du traitement. C'est un oubli ?


    Lié à ces histoires de libération, lorsque j'ajoute manuellement des composants dans un form, sont-ils bien détruits automatiquement à la fermeture du form ?

  2. #2
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 042
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 042
    Points : 40 955
    Points
    40 955
    Billets dans le blog
    62
    Par défaut
    Bonjour,

    Peut-être que c'est un interface, ce qui évite le besoin de "libération", j'ai pas eu le temps de vérifier dans les sources
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  3. #3
    Membre émérite
    Avatar de Thierry Laborde
    Homme Profil pro
    N/A
    Inscrit en
    Avril 2002
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : N/A

    Informations forums :
    Inscription : Avril 2002
    Messages : 1 391
    Points : 2 529
    Points
    2 529
    Par défaut
    Bonjour,

    Un Composant (Classe TComponent minimum) a 1 propriété qui est très importante et qui n'existe pas sur un objet : Le Owner.
    Le Owner est le propriétaire du composant. Il est indiqué à la création du composant. Donc ici :

    TaskDialog := TTaskDialog.Create(Self);
    Le owner est : Self, donc c'est la form qui est propriétaire du composant.
    Le rôle du propritétaire est de libérer tous les composants dont il est le propriétaire lorsqu'il est détruit. Donc quand la form est détruite elle détruite automatiquement tous les composants dont elle est propriétaire.
    Pour info, à la conception, quand je dépose un composant sur une Form, le propriétaire du composant est automatiquement la Form.

    ATTENTION, je pourrais créer dynamiquement un composant sans Owner, comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     TaskDialog := TTaskDialog.Create(Nil);
    Dans ce cas là le composant n'a pas de Owner et il faudra obligatoirement que je le détruise par le biais du code.

  4. #4
    Membre émérite
    Avatar de Thierry Laborde
    Homme Profil pro
    N/A
    Inscrit en
    Avril 2002
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : N/A

    Informations forums :
    Inscription : Avril 2002
    Messages : 1 391
    Points : 2 529
    Points
    2 529
    Par défaut
    Je rajouterai une précision, attention de ne pas confondre le Parent et le Owner sur un composant.

  5. #5
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    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 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Citation Envoyé par Thierry Laborde Voir le message
    Je rajouterai une précision, attention de ne pas confondre le Parent et le Owner sur un composant.
    Mais au niveau libération, c'est plus bien tordu : https://www.developpez.net/forums/d6.../parent-owner/

    Citation Envoyé par benoit1024 Voir le message
    C'est un oubli ?
    Je ferais un mail via le menu feedback en bas de page pour leur proposer la correction "create try finally free" que le code soit propre.
    Avoir un Create avec Owner sur une variable locale, ce n'est pas terrible
    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

  6. #6
    Membre émérite
    Avatar de ALWEBER
    Homme Profil pro
    Expert Delphi
    Inscrit en
    Mars 2006
    Messages
    1 496
    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 496
    Points : 2 762
    Points
    2 762
    Billets dans le blog
    10
    Par défaut
    C'est un oubli. Le "destructor" effectue entre autres les opérations suivantes
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    destructor TCustomTaskDialog.Destroy;
    begin
      FButtons.Free;
      FCustomFooterIcon.Free;
      FCustomMainIcon.Free;
      FProgressBar.Free;
      FRadioButtons.Free;
      inherited;
    end;

  7. #7
    Invité
    Invité(e)
    Par défaut
    Merci de vos précisions, je vais creuser.
    Je ne comprenais effectivement pas le rôle de owner, que j'avais tendance à confondre effectivement avec le parent.

  8. #8
    Membre expert
    Avatar de pprem
    Homme Profil pro
    MVP Embarcadero - formateur&développeur Delphi, PHP et JS
    Inscrit en
    Juin 2013
    Messages
    1 876
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : MVP Embarcadero - formateur&développeur Delphi, PHP et JS
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2013
    Messages : 1 876
    Points : 3 611
    Points
    3 611
    Par défaut
    Il me semble aussi plus propre de libérer la mémoire allouée quand l'objet n'a pas de raison de rester au delà de la portée de son pointeur.

    Dans le cas présent, dans un FormCreate, c'est un peu bizarre, mais en effet il devrait y avoir libération après avoir récupéré le résultat du Execute.

    Citation Envoyé par ShaiLeTroll Voir le message
    Avoir un Create avec Owner sur une variable locale, ce n'est pas terrible
    Je ne vois pas ce qui te dérange dans le fait de déclarer une variable locale pour allouer une zone mémoire avec un objet ou un composant ensuite rattaché à autre chose.

    C'est comme si on avait fait un moche "with ttaskdialog.create(self) do begin end" sans déclarer la variable du coup.

  9. #9
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    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 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Oui c'est un abus de langage, je voulais dire "Create avec Owner" avec une instance que l'on sait avec une durée de vie locale
    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

  10. #10
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Mais au niveau libération, c'est plus bien tordu : https://www.developpez.net/forums/d6.../parent-owner/
    c'est intéressant, je vais passer du temps à lire tout ça

  11. #11
    Invité
    Invité(e)
    Par défaut
    J'ai lu la cette discussion.

    Je comprends bien que les composants sont détruits par leur owner ou parent.

    Par contre, je n'arrive pas à comprendre l'erreur postée par Paul.
    Pourquoi FPanel est déjà à nil, qui l'a détruit ?

    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
    type
      TForm1 = class(TForm)
        Frame1: TFrame1;
      end;
    // ...
      TFrame1 = class(TFrame)
      private
       FPanel : TPanel;
      public
       constructor Create(AOwner: TComponent);
       destructor Destroy; override;
      end;
     
    constructor TFrame1.Create(AOwner: TComponent):
    begin
      inherited;
      FPanel := TPanel.Create(Self);
      FPanel.Parent := Self.Parent;
    end;
     
    destructor TFrame1.Destroy;
    begin
      FPanel.Free; // inutile, mais n'aurait pas du planter...mais si :)
      inherited;
    end;
    De ce que je croyais comprendre :
    En se détruisant, TForm1 détruit Frame1.
    En étant détruit Frame1 libère FPanel.

    Comme FPanel est déjà détruit, ce serait TForm1 qui l'aurait détruit avant ?

  12. #12
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    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 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    FPanel.Parent := Self.Parent;
    Cette ligne est très importante sur la gestion du Parent et montre la subtilité avec le Owner

    Justement FPanel n'est pas à nil et du coup le Free plante en essayant de libérer une deuxième fois le FPanel
    FPanel est libéré par le Parent car FPanel n'est pas dans la Frame mais placé en dehors, la libération de FPanel et Frame1 c'est même parent que l'effectue (Form1)
    La libération est faite du dernier au premier, du coup FPanel est libéré juste avant Frame1
    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
    Invité
    Invité(e)
    Par défaut
    J'avais mal lu le code, La parent de FPanel, n'est pas Self mais Self.Parent, donc TForm1 !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    FPanel.Parent := Self.Parent;
    J'ai donc bien compris. Dommage que je ne puisse pas mettre résolu une deuxième fois

  14. #14
    Membre émérite
    Avatar de ALWEBER
    Homme Profil pro
    Expert Delphi
    Inscrit en
    Mars 2006
    Messages
    1 496
    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 496
    Points : 2 762
    Points
    2 762
    Billets dans le blog
    10
    Par défaut
    Si je ne me trompe pas ce code est une erreur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    FPanel.Parent := Self.Parent;
    Voici le code que j'avais publié en 2009 mis à jour pour les version récentes de Delphi
    Une fois le programme lancé tu peux cliquer sur l'un des TPanel
    Fichiers attachés Fichiers attachés
    • Type de fichier : zip D3.zip (1,6 Ko, 40 affichages)

  15. #15
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par ALWEBER Voir le message
    Si je ne me trompe pas ce code est une erreur
    Non, c'est un exemple qu'avait donnée Paul pour expliquer justement comment il avait compris le fonctionnement des owners.
    C'est dans le lien donnée par ShaiLeTroll dans cette discussion.

  16. #16
    Membre émérite
    Avatar de ALWEBER
    Homme Profil pro
    Expert Delphi
    Inscrit en
    Mars 2006
    Messages
    1 496
    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 496
    Points : 2 762
    Points
    2 762
    Billets dans le blog
    10
    Par défaut
    Citation Envoyé par benoit1024 Voir le message
    Non, c'est un exemple qu'avait donnée Paul pour expliquer justement comment il avait compris le fonctionnement des owners.
    C'est dans le lien donnée par ShaiLeTroll dans cette discussion.
    Je sais j'avais participé à cette discussion en 2009 et oui déjà
    .
    Pour exemple tu créée une fiche avec un objet TPanel. Dans le onActivate tu met le code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    ShowMessage(Panel1.Owner.Name);
    ShowMessage(Panel1.Parent.Name);
    ShowMessage(Form1.Parent.name);
    La troisième ligne te sort une erreur car la propriété Parent d'un TForm est toujours à NIL
    Donc si tu écris "FPanel.Parent := Self.Parent;" cela revient à écrire "FPanel.Parent := NIL" ce qui ne peut que te poser des problèmes
    Regardes bien aussi l'exemple que je t'ai envoyé dans mon post précédent

  17. #17
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par ALWEBER Voir le message
    La troisième ligne te sort une erreur car la propriété Parent d'un TForm est toujours à NIL
    Donc si tu écris "FPanel.Parent := Self.Parent;" cela revient à écrire "FPanel.Parent := NIL" ce qui ne peut que te poser des problèmes
    Regardes bien aussi l'exemple que je t'ai envoyé dans mon post précédent
    C'est bon, j'ai bien compris.

    "FPanel.Parent := Self.Parent;" c'est bizarre, mais ça ne pose pas de problème.
    Self fait référence à TFrame1 et Self.Parent à TForm1.
    C'est donc TForm1 qui détruit FPanel.

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

Discussions similaires

  1. JTabbedPane et composants (libération de la mémoire)
    Par Patrice Henrio dans le forum Composants
    Réponses: 0
    Dernier message: 24/04/2012, 15h42
  2. Réponses: 1
    Dernier message: 23/06/2002, 00h15
  3. Redéfinir l'événement OnExit de mon composant TEditFloat
    Par Seb des Monts dans le forum C++Builder
    Réponses: 5
    Dernier message: 18/06/2002, 16h10
  4. Installer ses composants
    Par Geronimo dans le forum C++Builder
    Réponses: 14
    Dernier message: 18/06/2002, 14h51
  5. Re-dimensionnement automatique de composants
    Par ludo_7 dans le forum C++Builder
    Réponses: 10
    Dernier message: 16/05/2002, 16h35

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