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

Lazarus Pascal Discussion :

Impossible de libérer une stringlist dynamiquement créée [Lazarus]


Sujet :

Lazarus Pascal

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Expert confirmé
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 132
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 132
    Par défaut Impossible de libérer une stringlist dynamiquement créée
    Bonjour,

    J'ai encore un truc à m'arracher les cheveux, heureusement qu'ils repoussent vite !

    Je veux récupérer des noms de dossiers et des noms de fichiers depuis un TShellTreeView pour les insérer dans une TListbox, enfantin me direz-vous.
    Oui, c'est ce que je croyais, j'ai donc attaqué avec 4 lignes juste pour voir si l'idée fonctionnait, ce qui est le cas, mais mal, car je ne peux pas libérer les TStringList's créées...
    La preuve :
    J'ai lancé le projet et j'ai cliqué sur 3 nœuds, à la clôture j'ai gagné 9 unfreed memory block.
    J'ai recommencé avec 4 clics et là, 12 unfreed memory blocks, donc 1 clic = 3 unfreed blocks et voilà le code ultra-simple à l'origine de cette embrouille :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    function TForm1.ListDirectory(SelectedNode {as FolderSource}: string): TStrings;
    var sl: TStringList;
    begin
      sl:= TStringList.Create;
      sl.Add(SelectedNode); // pour test
      Result := sl; // ok
    //  sl.Destroy;  //sl.Free; //l'un comme l'autre = erreur
    end;
    Nom : sigsegv.png
Affichages : 112
Taille : 24,8 Ko
    En pas à pas, ça se produit au end; de fin de fonction.

    La manière d'appeler cette fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    procedure TForm1.stvClick(Sender: TObject);
    begin
      lbFonts.Items := ListDirectory(stv.GetPathFromNode(stv.Selected));
      // GetPathFromNode returns the path (including the file name) 
      // from the file system that a particular node represents. 
    end;
    Ça fonctionne, les données que j'attends se retrouvent bien dans la listbox, c'est juste ces fuites qui me perturbent.
    Quelque chose d'énorme doit m'échapper, mais je ne vois pas quoi...

    Ce que je vois, par contre, dans l'aide et que je ne comprend pas, c'est l'absence de Free, mais comme vous le voyez dans le code, un essai avec Destroy retourne la même erreur.

    J'ai jeté un œil à la pile d'appel, mais c'est ardu (dernière entrée en haut) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #0 SYSTEM$_$TOBJECT_$__$$_INHERITSFROM$TCLASS$$BOOLEAN at :0
    #1 fpc_do_is at :0
    #2 ?? at :0
    #3 ASSIGN(0x7ffff60b2200, 0x7ffff60b4e00) at gtk2int.pas:612
    #4 SETITEMS(0x7ffff5734ef0, 0x7ffff60b4e00) at include/customlistbox.inc:587
    #5 STVCLICK(0x7ffff6403790, 0x7ffff5730f10) at unit1.pas:139 <-- c''est bien la ligne qui appelle la fonction ListDirectory sur l''événement stvClick.
    avant c''est pas intéressant
    Alors, si quelqu'un a une idée, merci de la poster...

  2. #2
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 933
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 933
    Par défaut
    Les fuites sont logiques puisque tu crées des listes que tu ne libères pas.
    Le problème est que si tu les libères, Result devient invalide puisqu'il partage la même allocation ; d'où la VA.

    Tu dois mémoriser le pointeur retourné et le libérer une fois assigné à la ListBox.

    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
    procedure TForm1.stvClickClick(Sender: TObject);
    var
      List :TStrings;
    begin
      List := ListDirectory(stv.GetPathFromNode(stv.Selected));
     
      try
        lbFonts.Items.Assign(List);
      finally
        List.Free;
      end;
    end;
     
    function TForm1.ListDirectory(SelectedNode: string): TStrings;
    begin
      Result := TStringList.Create;
      Result.Add(SelectedNode));
    end;
    Mais des créations à gauche et des libérations à droite n'est pas exceptionnel. Plus simplement, passe ListBox.Items en paramètre (comme tu l'as vu dans d'autres fonctions dernièrement), la méthode appelée se contentant de la remplir.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    procedure TForm1.stvClickClick(Sender: TObject);
    begin
      ListDirectory(stv.GetPathFromNode(stv.Selected), lbFonts.Items);
    end;
     
    procedure TForm1.ListDirectory(SelectedNode: string; aList :TStrings);
    begin
      aList.Add(SelectedNode);
    end;

  3. #3
    Expert confirmé
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    11 132
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 11 132
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    ... Result devient invalide puisqu'il partage la même allocation
    Je me doutais, au vu du comportement de mes lignes de code, qu'il s'agissait d'un truc comme ça, mais j'étais à des années-lumière de le corriger aussi bien que tu l'as fait.
    T'es vraiment un cador, hein !

    Moi je pensais bêtement que Result := sl; se contentait de mettre les données de sl dans Result, un peu comme quand je donne une pièce de monnaie à quelqu'un, la pièce je ne l'ai plus et le quelqu'un s'en va et peut l'utiliser.
    Bah...

    Bonne journée et encore merci,

  4. #4
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 933
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 933
    Par défaut
    Citation Envoyé par Jipété Voir le message
    T'es vraiment un cador, hein !
    Arrête ! tu vas me faire

    Citation Envoyé par Jipété Voir le message
    Moi je pensais bêtement que Result := sl; se contentait de mettre les données de sl dans Result, un peu comme quand je donne une pièce de monnaie à quelqu'un, la pièce je ne l'ai plus et le quelqu'un s'en va et peut l'utiliser.
    Mais c'est un peu ça à part qu'ici il ne donne pas une pièce (un item) mais tout le porte-monnaie (l'allocation complète)
    Pour être plus précis, ils partagent le même porte-monnaie et si un le jette l'autre ne peut plus l'utiliser non plus.

    L'incompréhension vient plutôt du comportement des propriétés qui implémentent des accesseurs (getter/setter = encapsulation) comme ListBox2.Items := ListBox1.Items qui se traduit en fait par ListBox2.SetItems(ListBox1.FItems), SetItems lançant lui-même un Assign pour la copie de la données (ce que tu retrouves dans la pile d'appels lors de l'erreur).

    Mais ceci n'a pas cours ici puisqu'une copie de pointeur n'est pas orientée objet

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

Discussions similaires

  1. [JSP] Impossible de faire une inclusion dynamique
    Par hans88 dans le forum Servlets/JSP
    Réponses: 2
    Dernier message: 14/10/2011, 10h58
  2. [Débutant] impossible de fermer une fiche créée dynamiquement à l'aide d'un bouton
    Par sergeprd dans le forum C++Builder
    Réponses: 11
    Dernier message: 26/07/2011, 09h57
  3. [XSLT] Intégrer une image SVG créée dynamiquement
    Par HomoErectus dans le forum XSL/XSLT/XPATH
    Réponses: 4
    Dernier message: 01/09/2009, 10h32
  4. Comment savoir si une StringList a été créée ?
    Par defluc dans le forum Composants VCL
    Réponses: 5
    Dernier message: 04/11/2008, 06h16
  5. Réponses: 3
    Dernier message: 10/06/2007, 21h53

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