7
votes

À Delphi 5, peut-on libérer de toujours soulever une exception?

dans Delphi 5, j'ai actuellement écrit le code qui appelle gratuit code> sur plusieurs variables dans un bloc enfin code>, par exemple

...
finally
    a.Free;
    b.Free;
    c.Free;
end;


4 commentaires

Pourquoi le bowvote hors d'intérêt? C'est une question claire, il n'y a pas d'ambiguïté et je voulais vraiment connaître la réponse. haussement d'épaules


Je pense que vous avez accepté une réponse ici trop vite.


@NGLN: D'accord en fait (désolé Tondrej), je pense que la réponse de David est bien meilleure.


@Stuartgolodetz Pas de problème, je suis d'accord.


5 Réponses :


3
votes

dépend de ce qui se passe dans le destructeur.


1 commentaires

Totalement correct, j'ai supprimé mon mauvais anser. N'a pas pris en compte les destructeurs. C'est pourquoi les destructeurs ne doivent pas lancer d'exceptions.



0
votes

bien sûr libre peut émettre des exceptions - alors oui, vous allez étanche de la mémoire dans votre code si A.Free émet une exception, B.Free et C.Free ne sera pas appelée.

La question est, voulez-vous Pour gérer les exceptions ou les laisser arriver? Son dépend de ce que votre code va être pour, d'autres devs vont l'utiliser (par exemple). Pour éviter toute fuite de mémoire, vous devez nicher les sections Essayy..Finalement; P>

a:=tobject.create;
try
  b:=tobject.create;
  try
    c:=tobject.create;

    ...

  finally
    c.free;
  end;
finally
  b.free;
end;
a.free;


4 commentaires

Votre a.free; est en dehors de tout Essayez .. enfin , et vous essayez de libérer B si < Code> B: = tobject.create; soulève une exception (même avec C ).


En outre, si c.free soulève une exception, vous avez toujours une fuite car vous n'avez pas réellement libéré c .


Son déblable que c'est un bon style de codage de toute façon - mais j'ai dit que vous devriez probablement essayer. Je faisais seulement démontrer comment vous pourriez le faire :-)


Dans votre exemple, vous devez définitivement envelopper le a.free; dans un essayer .. enfin aussi. Si vous êtes absolument sûr à 100% duquel le code ne peut jamais soulever une exception, vous n'en avez pas besoin, mais vous n'avez alors besoin d'aucun des essayer .. enfin s que vous avez inclus.



1
votes

Si votre fichier A.Free augmente une exception, a (en fonction de la quantité que le destructeur a libéré des champs d'objets d'A), les objets B et C seront des fuites car l'exécution sera interrompue. Quoi qu'il en soit, quelque chose ne va pas dans votre destructeur, s'il augmente une erreur. Donc, vous devriez protéger le code avec des blocs tressant.


5 commentaires

L'hypothèse de Stuart est «GRATUITE PEUT PAS SUPPORTER UNE EXCEPTION», et cela peut clairement.


N'oubliez pas, le A va également fuir si son destructeur augmente une exception.


En fait, je voulais dire A fuira toujours, car la mémoire pour A ne sera définitivement pas libérée, mais vous avez raison de souligner que certaines de ses sous-observations peuvent être.


Merci a tous. Je viens à ce sujet à partir d'un fond de C ++, où les destructeurs pouvant lancer sont un NO sérieux non-non (depuis la lancée tandis que la pile est déroulée à la suite d'une exception précédente std :: terminer ), donc j'ai fait la (ce qui s'avère être invalide) en supposant que quelque chose de similaire était le cas à Delphi.


@StuartgolodeZ L'application ne se termine pas sur Delphes Double Exceptions près, mais cela ne signifie pas que l'élévation d'exceptions d'un destructeur est une bonne idée. Vous ne devriez jamais le faire à Delphes non plus. :)



11
votes

La méthode libres ne constitue pas explicitement une exception, mais elle appelle le destructeur virtuel détruire qui pourrait certainement soulever une exception.

Donc si vous voulez Assurez-vous que tous vos objets sont détruits, même si l'un des destructeurs augmente une exception, vous vous retrouvez avec un code comme celui-ci: xxx

ayant dit que, il devrait être une conception Principe que vous ne soulevez pas d'exceptions dans un destructeur. Donc, à mon avis, il est parfaitement raisonnable de prendre le point de vue que si une exception est élevée en destructeur, votre programme est à peu près rechangé. Les objets qui fuient à ce stade ne sont pas quelque chose à craindre. Si votre destructeur a soulevé une exception, vous allez probablement déjà fuir parce que ce destructeur ne s'est pas exécuté à l'achèvement.

donc à mon avis, il peut être parfaitement raisonnable de regrouper certains appels vers Gratuit et bien sûr, vous éviterez profondément imbriqué essayer / enfin qui est quelque chose qui mérite d'être visible pour.

si vous voulez juste un essayer < / code> / enfin puis rappelez-vous d'écrire le code comme celui-ci: xxx

dans ma propre base de code, j'ai quelques méthodes d'assistance qui rendent ce nettoyant . Ensuite, le code peut ressembler à ceci: xxx

J'ai donné mon freeandnil le même nom que la fonction dans sysutils Lequel sur le premier coup d'œil peut sembler étrange, mais c'est sûr et bénin de le faire. Naturellement, ces aides entrent dans leur propre lorsque vous avez encore plus de deux objets.


0 commentaires

2
votes

Il pourrait y avoir 2 choses pouvant causer personnobj.free pour soulever une exception:

  1. Exception non confondue à la destructeur du Someobj instance de classe ou de ses ancêtres.
  2. Référence de classe non valide due à une variable non initialisée TOOOBJ .

    Dans votre cas si a.free soulève une exception pour les raisons ci-dessus, il y aurait une fuite de mémoire pour objet B et C et peut-être une fuite à l'intérieur de l'objet A à cause de l'exception non gérée dans lestructeurs.


0 commentaires