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 :

Free ne "libère" pas l'objet


Sujet :

Langage Delphi

  1. #1
    Membre confirmé
    Avatar de Higgins
    Inscrit en
    Juillet 2002
    Messages
    520
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 520
    Points : 543
    Points
    543
    Par défaut Free ne "libère" pas l'objet
    Bonjour,

    J'avais pris l'habitude d'utiliser "FreeandNil" plutôt que free pour libérer mes objets. Je reconnais que c'était surtout parce que (trop) souvent, j'oubliais dans mon code d'en libérer dans les "destroy" certains https://www.developpez.net/forums/im...milies/aie.gif

    Cet été, j'ai suivi un peu le débat "pour ou contre Freeandnil()"

    J'en ai déduit qu'un code "propre" devait, globalement, pouvoir se passer de FreeAndNil.
    Dans l'exemple de code ci-dessous, la commande "test.free" ne libère pas la mémoire. Si je ne réutilise pas la variable ensuite, il ne devrait pas y avoir de problème mais dans le cas d'un service qui tourne 24h/24h, cet emplacement mémoire finit-il par être libéré?ne risque-t-il pas, à terme, d'y avoir une saturation de la mémoire?
    Est-ce que "free" ne libère pas la mémoire "by design" ou est-ce un bug à signaler à Embarcadero?
    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
     
    program Project5;
     
    {$APPTYPE CONSOLE}
     
    {$R *.res}
     
    uses
      System.SysUtils,system.Classes;
     
      type  TMaClasse=class(TPersistent)
      private
       fID:integer;
       fNom:string;
      public
        property ID:integer read fID write fID;
        property Nom:string read fNom write fNom;
     
      end;
     
      var test:TMaClasse;
     
    begin
      try
        { TODO -oUser -cConsole Main : Insérer du code ici }
        //ici test=nil
        test:=TMaclasse.Create;
        test.ID:=1;
        test.Nom:='essai';
        writeln('ID='+test.ID.ToString+';NOM='+test.Nom);
        test.Free;
        //ici, test devrait être "libéré "et ne plus occuper de place en mémoire
        if (test<>nil) and (assigned(test)) then
        begin
          //On ne devrait pas arriver jusqu'ici...
          //....et cette ligne devrait provoquer une violation d'accès
           writeln('ID='+test.ID.ToString);
           //... mais ce n'est pas le cas
           readln;
        end;
      except
        on E: Exception do
          Writeln(E.ClassName, ': ', E.Message);
      end;
    end.

  2. #2
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 875
    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 875
    Points : 11 365
    Points
    11 365
    Billets dans le blog
    6
    Par défaut
    Bonjour,
    Quand on crée test, cela réserve pour l'objet nouveau une zone mémoire pointée par la variable test.
    Au Free, cette mémoire est rendue au gestionnaire de mémoire qui pourra la réutiliser à sa guise et n'est pas tenu de l'effacer ou de s'en resservir immédiatement.
    Et, surtout, test.Free n'a aucune action sur la valeur de la variable test, à la différence du FreeAndNil(test).
    C'est donc ta responsabilité de ne pas appeler un objet que tu as libéré, un moyen étant de ne pas garder de référence dessus.

    Quant au gestionnaire de mémoire, il finit par réallouer des zones libérées en fonction des besoins, de la granularité des "trous de mémoire", etc. Il est vrai que si un programme créait indéfiniment des objets toujours plus grands que ceux déjà libérés, ça finirait sûrement mal !

  3. #3
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 735
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 735
    Points : 5 406
    Points
    5 406
    Par défaut
    Pour paraphraser et simplifier ce que dit @tourlourou :

    test.Free ne va pas mettre test à nil.
    Il faut le faire manuellement.

  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 : 55
    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 457
    Points
    28 457
    Par défaut
    Citation Envoyé par popo Voir le message
    Pour paraphraser et simplifier ce que dit @tourlourou :

    test.Free ne va pas mettre test à nil.
    Il faut le faire manuellement.
    ou pas...selon le besoin

  5. #5
    Membre confirmé
    Avatar de Higgins
    Inscrit en
    Juillet 2002
    Messages
    520
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 520
    Points : 543
    Points
    543
    Par défaut
    Merci à vous pour ces précisions.
    Je vais donc rester sur mon FreeAndNil() habituel. Il me semble plus sûr de déréférencer les objets après un free pour éviter tout problème.
    Comme en plus mon code métier est commun à plusieurs applications dont un service qui tourne 24h/24h et qui est très sollicité, je préfère anticiper tout risque de saturation de la mémoire (déjà expérimenté avec de précédentes versions de Delphi)

  6. #6
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 586
    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 586
    Points : 25 262
    Points
    25 262
    Par défaut
    Et sans oublier FastMM qui désalloue la mémoire par lot, on peut donc très bien encore lire de la mémoire tant que le lot complet n'est pas libéré (ou réutilisé)

    Free libère mais ne vide pas la mémoire, elle reste à la valeur qu'elle était, donc on peut encore lire des résidus.
    Faire un ZeroMemory c'est couteux en temps, c'est 90% du temps d'un SetLength sur un tableau par exemple (sur FastMM, avant c'était l'inverse ou presque)


    Savoir gérer la portée et le cycle de vie d'un objet semble une chose difficile ... normal avec le Java et C# qui assistent les développeurs paresseux.
    D'où l'importance d'éviter les variables globales, de respecter la visibilité (strict private par exemple), toujours utiliser des accesseurs pour gérer l'affectation par copie dans certains cas....

  7. #7
    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 : 55
    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 457
    Points
    28 457
    Par défaut
    Citation Envoyé par Higgins Voir le message
    Merci à vous pour ces précisions.
    Je vais donc rester sur mon FreeAndNil() habituel. Il me semble plus sûr de déréférencer les objets après un free pour éviter tout problème.
    Comme en plus mon code métier est commun à plusieurs applications dont un service qui tourne 24h/24h et qui est très sollicité, je préfère anticiper tout risque de saturation de la mémoire (déjà expérimenté avec de précédentes versions de Delphi)
    affecter "nil" à un objet n'a aucune incidence sur la mémoire...cela permet simplement de tester s'il est à nil ou pas.

    exemple (en considérant que le code s'exécute malgré les exceptions)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    var
      b: TButton; // n'est probablement pas nil
    begin
      b := TButton.Create(Self); // il n'est pas à nil
      b.Free; // l'objet est détruit mais b n'est toujours pas à nil
      b.Caption := 'hello', // violation d'accès car on utilise un pointeur invalide
      if Assigned(b) then // le test passe car b n'est pas à nil
        b.Caption := 'tutu'; // violation d'accès car on utilise un pointeur invalide
      b := nil; // b est à nil
      b.Caption := 'toto'; // violation d'accès car on utilise un pointeur nul
      if Assigned(b) then // le test ne passe pas car b est nul
        b.Caption := 'tutu'; // pas d'erreur car pas d'exécution
    end;
    FreeAndNil() c'est juste pour faire Free et Nil en une seule opération, pour le reste ça ne change rien

  8. #8
    Membre confirmé
    Avatar de Higgins
    Inscrit en
    Juillet 2002
    Messages
    520
    Détails du profil
    Informations forums :
    Inscription : Juillet 2002
    Messages : 520
    Points : 543
    Points
    543
    Par défaut
    Citation Envoyé par Paul TOTH Voir le message
    affecter "nil" à un objet n'a aucune incidence sur la mémoire...cela permet simplement de tester s'il est à nil ou pas.
    Je pensais que ça "accélérait" la prise en charge par le gestionnaire de mémoire et donc la libération de l'espace mémoire associé.

    De toutes façons, j'ai l'habitude de toujours tester la validité des paramètres reçus par les procédures/fonctions et donc de vérifier qu'un objet n'est pas à nil donc...il vaut mieux que j'utilise FreeAndNil

  9. #9
    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 614
    Points
    3 614
    Par défaut
    Citation Envoyé par Higgins Voir le message
    Je pensais que ça "accélérait" la prise en charge par le gestionnaire de mémoire et donc la libération de l'espace mémoire associé.
    En fonctionnement normal non.
    Avec ARC sur les plateformes mobiles dans les versions antérieures à la 10.4 ça a pu jouer, mais mieux vaut ne pas coder pour ARC vu qu'on s'en est débarrassé (pour les objets).

  10. #10
    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 776
    Points
    2 776
    Billets dans le blog
    10
    Par défaut Une autre piste
    Regardes aussi du côté de 'System.TObject.DisposeOf'

  11. #11
    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 614
    Points
    3 614
    Par défaut
    Citation Envoyé par ALWEBER Voir le message
    Regardes aussi du côté de 'System.TObject.DisposeOf'
    Ou pas...

    https://docwiki.embarcadero.com/Libr...ject.DisposeOf

  12. #12
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 586
    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 586
    Points : 25 262
    Points
    25 262
    Par défaut
    On note que la version FR n'est pas à jour avec l'obsolescence décrite en EN !

  13. #13
    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 614
    Points
    3 614
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    On note que la version FR n'est pas à jour avec l'obsolescence décrite en EN !
    excellente remarque, pareil pour la version allemande alors que la japonaise est à jour, j'fais un TODO, merci

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

Discussions similaires

  1. nom de domaine libre ou pas ?
    Par piff62 dans le forum Domaines
    Réponses: 2
    Dernier message: 20/04/2005, 14h09

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