Quel est préférable: gratuit ou FreeAndNil?

Quelle est la différence fondamentale entre Free et FreeAndNil?

Est FreeAndNil = Gratuit + Néant?

Quand devrais-je utiliser Free et quand devrais-je utiliser FreeAndNil?

Je ne reçois pas ces lunettes quand quelqu'un peut-il m'aider.

Merci d'avance.

43
demandé sur Andreas Rejbrand 2010-07-01 19:43:55

5 réponses

Voir

Et jetez un oeil à l'implémentation:

procedure FreeAndNil(var Obj);
var
  Temp: TObject;
begin
  Temp := TObject(Obj);
  Pointer(Obj) := nil;
  Temp.Free;
end;

Exemples

Considérons le code suivant:

procedure TForm1.FormCreate(Sender: TObject);
var
  bm: TBitmap;
begin
  bm := TBitmap.Create;
  bm.LoadFromFile('C:\Users\Andreas Rejbrand\Documents\RAD Studio\6.0\Demos\DelphiWin32\VCLWin32\Football\up.bmp');
  bm.Free;

  if Assigned(bm) then
    bm.SaveToFile('C:\Users\Andreas Rejbrand\Desktop\test.bmp')
  else
    ShowMessage('Cannot save! The bitmap does no longer exist!');
end;

Cela créera une erreur ou un bitmap invalide (vide) sur mon bureau, car je essayez d'utiliser un objet qui a été libérée. Oui, même si bm a été libéré, il est toujours "assigné", c'est-à-dire que bm pointe toujours vers une adresse mémoire, même s'il n'y a rien (utilisable) là. Pour surmonter cette difficulté, on peut définir bm := nil, comme une sauvegarde, Puis assigned(bm) retournera false, comme on voudrait. Plus ou moins, FreeAndNil(bm) est un raccourci pour bm.Free; bm := nil. La première instruction libère toute la mémoire (et les ressources du système D'exploitation, le temps CPU, etc. utilisée par l'objet), et bm := nil définit le "pointeur" bm à nil, de sorte que bm non plus pointe vers l'endroit où l'objet était, mais ne l'est plus. De cette façon, vous (et les routines comme assigned) ne vous laisserez pas berner de croire qu'il existe toujours un objet bitmap.

Discussion

Certains disent que vous devriez toujours utiliser FreeAndNil(foo) plutôt que foo.Free. Eh bien, pourquoi pas? L'instruction supplémentaire foo := nil ne prendra probablement pas trop de nanosecondes à exécuter, et en effet assigned(foo) = false est une très belle propriété d'un objet libéré. Mais là encore, si vous savez ce que vous faites, et sachez que vous n'utiliserez plus jamais l'objet foo après l'avoir libéré, alors vous pourriez vous en tenir à foo.free. Vraiment, certains diront que dans de nombreux cas (mais pas tous), essayez d'utiliser une variable d'un objet libéré est un bug en lui-même. (Bien sûr, il y a des cas où vous le faites intentionnellement-vous avez un objet foo qui est parfois assigné et parfois non.)

42
répondu Andreas Rejbrand 2012-06-25 12:06:51

Fondamentalement, FreeAndNil définit la référence à nil et libère ensuite l'objet. Cela le marque comme non affecté. Donc, la seule raison pour laquelle vous avez besoin d'utiliser FreeAndNil est si votre code va réutiliser la référence. Si vous êtes dans un destructeur ou un bloc enfin , libérant des objets que vous ne toucherez plus jamais, utilisez simplement Free.

Voir Delphi Memory Management Made Simple pour un exemple de quand je l'ai trouvé utile. Le commentaire de Mghie en bas est également la peine de lire.

18
répondu Mason Wheeler 2014-07-11 11:57:22

Je vais répondre d'une manière différente.

Peut-être, remplir votre référence d'objet avec nil après avoir libéré votre objet n'est pas toujours une bonne idée.

De Cette façon, vous n'avez pas de distinction entre une référence qui n'a jamais été (et est donc nil), et une référence qui a été utilisé, mais ne doit pas être utilisé dans l'avenir.

Donc, le remplir avec un nombre magique (similaire à ce que le gestionnaire de mémoire FastMM peut faire avec le contenu des blocs de mémoire lorsque ceux-ci les blocs sont libérés).

--jeroen

8
répondu Jeroen Wiert Pluimers 2010-07-01 19:07:51

@Bharat, la différence entre Free et FreeAndNil est que, en plus de libérer la mémoire utilisée par un objet FreeAndNil définit la référence d'objet nul.

Vous pouvez consulter ces liens pour des discussions sur l'utilisation de Free ou FreeAndNil

6
répondu RRUZ 2010-07-01 15:57:31

Même si cela ne semble pas être très différent de Free, cela vous aidera beaucoup plus tard lors de la chasse aux bogues de votre code.

Pensez simplement à ce qui se passe si vous N'utilisez pas FreeAndNil et que vous accédez à un objet libéré quelque part dans votre code. Si vous êtes terrible chanceux, votre programme va planter quand il fonctionne à la maison (Oui, c'est un crash est un " bon " crash). Si vous êtes un peu malchanceux, il va planter dans l'ordinateur du client. Alors la vraie douleur commence!

Comme d'autres l'ont déjà souligné, le FreeAndNil lui-même n'est pas mauvais. La fonction FreeAndNil n'est pas cassée / obsolète ou quelque chose comme ça et elle ne corrompra pas votre code. Certains diront que s'appuyer sur FreeAndNil peut conduire ou indiquer un défaut de conception.

J'utilise FreeAndNil même sur une variable locale. L'utiliser sur une variable locale semble inutile puisque la variable disparaît dès que vous quittez la procédure. Cependant, c'est une bonne pratique qui ne vous coûtera que quelques octets supplémentaires. Pensez que vous pouvez, à une date ultérieure ajouter plus de code à la fin de la procédure, après le point où vous avez libéré l'objet, le code qui va (évidemment accidentellement) essayer d'accéder à l'objet libéré. Si L'objet était NIL, BABUM, instant AV (exemple ).
Remarque: certaines personnes peuvent dire qu'elles n'ont jamais accédé à un objet libre (ce qui signifie essentiellement qu'elles ne font jamais d'erreurs), donc elles n'ont pas besoin de FreeAndNil dans ce cas. Eh bien, je ne suis pas un robot. Je fais des erreurs.

Certaines personnes conservatrices peuvent dire que cet appel simple gaspillera des ressources RAM et CPU. Je vais ne jamais dire que la conservation de la mémoire / CPU est mauvaise. J'aime aussi livrer des applications petites/rapides/monolithiques! Mais je ne pense pas que la suppression en utilisant FreeAndNil gaspillera plus de quelques octets et cycles CPU (littéralement peu). Cela ne fera pas une réelle différence dans la vie quotidienne, surtout quand vous pensez qu'une seule ressource graphique comme un glyphe TButton ou l'icône de votre programme peut prendre 50-300KB, et votre programme peut en avoir des dizaines.

Avantages
Mason Wheeler pointe déjà vers un article qui montre la méthode 'création paresseuse' qui utilise FreeAndNil que nous avons tous utilisé un jour: http://tech.turbu-rpg.com/106/delphi-memory-management-made-simple

Contre
Allen Bauer montre ici un exemple sur l'utilisation du FreeAndNil dans un certain cas (destructeur d'un composant visuel) et être en effet mauvais: http://blogs.embarcadero.com/abauer/2010/02/16/38916
Allen déclare que FreeAndNil devrait être remplacé par de meilleures méthodes. Par exemple avec FastMM. Cependant, voici un simple morceau de code où FastMM échoue alors que FreeAndNil enregistre le jour: http://codeverge.com/embarcadero.delphi.rtl/freeandnil-to-use-or-not-to-use/1067733

Comme il y a à la fois des arguments pour et contre FreeAndNil, c'est à vous de décider si vous le souhaitez ou non.

2
répondu Everybody_hates_BillTheLizard 2014-04-06 11:09:55