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 FMX Delphi Discussion :

Free ne libère pas la mémoire [Windows]


Sujet :

Composants FMX Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Avatar de Higgins
    Inscrit en
    Juillet 2002
    Messages
    539
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 539
    Par défaut Free ne libère pas la mémoire
    Bonsoir tout le monde,

    Voici mon problème: je développe sur XE7 et lorsque j'appelle la méthode free de ma classe, l'objet reste en mémoire et finit par provoquer des erreurs de ressources insuffisantes.
    Je libère bien tous les membres dans le destructeur, puis je les force à nil (car ils sont toujours là qd j'évalue le code) mais sans succès
    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
     
    type tclasse1=class(tObject)
    private
      fattribut1:int;
    public
       destructor destroy;override;
       constructor create;
    end;
     
    type tclasse2=class(tObject)
    private
      fattribut2:tclasse1;
    public
       destructor destroy;override;
       constructor create;
    end;
     
    constructor tclasse1.create;
    begin
     fattribut1=1;
    end;
     
    constructor tclasse2.create;
    begin
     fattribut2=tclasse1.create;
    end;
     
    destructor tclasse2.destroy;
    begin
     if fattribut2<>nil then
        fattribut2.free;
    end;
     
    procedure test;
    var variable:Tclasse2;
    begin
        variable:=Tclasse2.create;
        variable.free;
    end;
    Dans cet exemple, à la fin de la procédure test, l'attribut variable.fattribut2 est bien à nil mais variable n'est pas libéré alors que ce devrait être le cas.

    Avez-vous une piste?

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 948
    Par défaut
    Il manque inherited en fin de Destroy.

  3. #3
    Membre éclairé
    Avatar de Higgins
    Inscrit en
    Juillet 2002
    Messages
    539
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 539
    Par défaut
    j'ai oublié de le mettre mais il est bien présent dans mon code.
    voici le code exact sur une classe basique:
    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
     
    type TLanguage=class(Tobject);
    public
         Id:integer;
         name:string;
         owner:TObject;
    end;
     
    destructor TLanguage.Destroy;
    begin
     if owner<>nil then
        owner.free;
     inherited destroy;
    end;
     
    destructor TUserSession.Destroy;
    begin
     ......
     if language<>nil then
        language.free;
     inherited destroy;
    end;
    Si je place le curseur de la souris sur la ligne juste après l'avoir exécutée, l'explorateur de code affiche:
    (language| (ID=0,name='',owner=nil)
    alors que je m'attends à voir
    language=nil

    Ce phénomène se reproduit sur toutes mes classes et l'application ne cesse de grossir au cours du fonctionnement

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

    Informations professionnelles :
    Activité : Expert Delphi

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 544
    Billets dans le blog
    10
    Par défaut Infos complémentaires
    Bonjour,

    1) As tu essayé avec des objets dérivés de TPersistent
    2) Quel outil de mesure te permet de dire que tu pers de la mémoire ?

  5. #5
    Membre éclairé
    Avatar de Higgins
    Inscrit en
    Juillet 2002
    Messages
    539
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 539
    Par défaut
    1) même problème avec TPersistent
    2) La taille en mémoire de l'exécutable augmente au fur et à mesure de son utilisation jusqu'à provoquer une erreur "Mémoire insuffisante". Par ailleurs, après l'appel à free, mon instance devrait être égale à nil et ce n'est pas le cas.

  6. #6
    Rédacteur/Modérateur

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

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

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 664
    Billets dans le blog
    65
    Par défaut
    Bonjour,

    sans conviction aucune, je n'ai pas lu le code entier, pourquoi ne pas utiliser FreeAndNil(language);

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 948
    Par défaut
    Un Free ne met pas le pointeur à nil, il faut utiliser FreeAndNil pour ça.

    Ce TLanguage.Destroy ne me plait guère. Il détruit son propriétaire qui va sans doute vouloir libérer ses éléments qui voudront à leur tour détruire leur propriétaire, etc. une boucle sans fin jusqu'à saturation.

  8. #8
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 106
    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 106
    Par défaut
    Même remarque que AndNotOr

    Dans le dernier code, l'utilisation du terme "Owner" est ambiguë.
    Pour le TComponent, le Owner c'est l'objet qui libère les objets qu'il possède.
    Dans ton cas, c'est du TObject, mais évite le mot Owner qui est presque un mot clé Delphi

    Pense à changer le nom pour éviter que cela soit un piège dans une prochaine maintenance si c'est un Owner sans lien avec la mémoire,
    peut-être mettre User ou Session par exemple !

    De plus, utilise des property pour les membres public, c'est plus élégant et en particulier si l'objet ne doit pas être modifié par un autre objet en mettant une propriété en lecture seule
    cela t'évitera des modifications ultérieurs si tu dois un jour ajouté des contrôles via des accesseurs
    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 éclairé
    Avatar de Higgins
    Inscrit en
    Juillet 2002
    Messages
    539
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 539
    Par défaut
    Citation Envoyé par Andnotor Voir le message
    Un Free ne met pas le pointeur à nil, il faut utiliser FreeAndNil pour ça.
    Même résultat J'ai cru un instant que ça s'améliorait mais c'était tant que j'étais en pas à pas. Dès lors que j'exécute en "release", le pb revient

    Citation Envoyé par Andnotor Voir le message
    Ce TLanguage.Destroy ne me plait guère. Il détruit son propriétaire qui va sans doute vouloir libérer ses éléments qui voudront à leur tour détruire leur propriétaire, etc. une boucle sans fin jusqu'à saturation.
    En réalité le code est un peu plus complexe que j'ai mis et je te rassures, il n'y a pas de boucle infinie.

    Citation Envoyé par ShaiLeTroll
    De plus, utilise des property pour les membres public, c'est plus élégant et en particulier si l'objet ne doit pas être modifié par un autre objet en mettant une propriété en lecture seule
    En réalité, il y a des getter setter et des property pour chaque membre. J'ai juste mis du code allégé.

    Je vous remercie tous pour votre aide, mais j'ai décidé de contourner le problème. Il s'agit d'une simple application "moulinette" qui récupère des données d'une vieille base paradox, les mets en forme, leur applique des règles métiers, et les intègre dans une base SQL où elles seront utilisées par une autre application.
    L'exécution n'a lieu qu'une seule fois lors de la reprise de données. J'ai donc contourné le pb en relançant l'appli lorsqu'elle atteint une taille en mémoire paramétrable.
    Je mets donc le tag résolu et je vous remercie tous pour votre aide.

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

    Informations professionnelles :
    Activité : Expert Delphi

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 544
    Billets dans le blog
    10
    Par défaut
    Citation Envoyé par Higgins Voir le message
    1) même problème avec TPersistent
    2) La taille en mémoire de l'exécutable augmente au fur et à mesure de son utilisation jusqu'à provoquer une erreur "Mémoire insuffisante". Par ailleurs, après l'appel à free, mon instance devrait être égale à nil et ce n'est pas le cas.
    Bonjour,

    Effectivement tu dois utiliser FreeAndNil (TLanguage) plutôt que Free ou Destroy

    Peux tu modéliser un petit exemple pour pouvoir tester le problème en indiquant la version de Delphi que tu utilises. La solution passe peut-etre par quelque chose qui se rapproche du singleton

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

Discussions similaires

  1. Réponses: 7
    Dernier message: 13/08/2014, 17h57
  2. Garbage Collector ne libère pas de mémoire
    Par Nico2050 dans le forum Général Java
    Réponses: 4
    Dernier message: 15/11/2012, 00h21
  3. mqsvc.exe ne libère pas sa mémoire
    Par Kagozuma dans le forum Général Dotnet
    Réponses: 6
    Dernier message: 12/08/2011, 12h39
  4. Réponses: 18
    Dernier message: 08/04/2009, 10h19
  5. [JDialog] La mémoire ne se libère pas au dispose()
    Par bugalood dans le forum Agents de placement/Fenêtres
    Réponses: 9
    Dernier message: 01/09/2005, 22h31

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