Delphi et finalisation dans une unité de
J'ai deux unités de l'unitA et unitB.
Classe TFoo est déclaré dans unitB.
Est-il toujours possible d'appeler B. Libre dans la finalisation de l'unitA?
Comment cela dépend-il de l'ordre dans lequel l'unitA et unitB sont dans le dpr?
Puis-je être sûr que unitB existe lors de la finalisation de l'unitA est exécuté?
unit unitB;
interface
type
TFoo = class
// code...
end;
// code....
end;
unit unitA;
// code..
implementation
uses
unitB;
var
A: TStringList;
B: UnitB.TFoo;
initialization
A:= TStringList.Create;
B:= UnitB.TFoo.Create;
finalization
A.Free;
B.Free; // Is it safe to call?
end.
OriginalL'auteur pKarelian | 2010-02-20
Vous devez vous connecter pour publier un commentaire.
Oui, vous devriez être bien puisque B est créé dans l'Unité A. La règle est que l'Initialisation sections sont appelés en fonction de l'ordre dans le RMR, sauf si l'une des unités de références d'une autre unité. Dans ce cas, la référence de l'unité est d'abord initialisé. La finalisation est dans l'ordre inverse.
Dans votre cas, l'Unité B n'a pas de section initialisation, donc c'est un point discutable. Il faudra cependant utiliser le TFoo définition de l'Unité B lorsque l'Unité d'Une section initialisation est exécutée.
Un mot d'avertissement au sujet de l'Initialisation et de la Finalisation de sections qu'ils se produisent à l'extérieur de la global gestionnaire d'exception. Toute exception qui se produit là juste met fin à l'application. Donc, la traque et le débogage de ces exceptions peuvent être une douleur dans de grands programmes. Vous pourriez envisager d'utiliser votre propre enregistrement d'exception là, juste pour être sûr.
Voir mon commentaire. Delhi n'est pas garant de l'ordre. Votre exception remarque est vraie.
Il vaut la peine de noter que Madexcept captures de ces exceptions soulevées dans la finalisation des sections.
OriginalL'auteur Jim McKeeth
PAS. Vous pouvez essayer, vous pouvez espérer, mais il n'y a aucune garantie dans l'ordre d'appel d'initialisation et de mise au point. Voir qc72245, qc56034 et beaucoup plus de.
Mise à JOUR:
Exemple:
Commun (correcte) de l'ordre (à 99,99%) de la demande:
Mais parfois peut Delphi compilation de fichier incorrecte:
Peu offtopic histoire:
Nous avons assez gros projet, avec Type1 dans Unit1, Type2 = classe(Type1) dans Unite2. Les fichiers sont classés dans le projet.les rmr et après des années et en ajoutant Unit200 (pas de dépendance avec part1/2) Delphi commence à rassembler projet avec Unite2.Initialisation avant de Part1.L'initialisation. Seule solution sûre est d'appeler vos propres fonctions d'Initialisation à partir de l'initialisation de la section.
Même si l'unité B est finalisé la première, qui n'entraîne pas l'appareil à l'arrêt existant. Le Code qui utilise des choses définies dans l'unité B va continuer à travailler.
Mais il dépend. finalisation pièces de exécutées dans l'ordre inverse de l'initialisation, mais Delphi pouvez échanger des parts et de l'ordre
OriginalL'auteur DiGi
Aussi loin que je comprends bien ce que vous avez doit être parfaitement valide. Un peu maladroit, mais valide.
Mais une meilleure façon peut-être pour déclarer une variable dans l'Unité B et B ont initialiser/le finaliser.
Depuis initialisations se passer avant tout autre code est appelé il sera initialiser avant de les rendre disponibles à l'Unité A tant qu'il est déclaré dans la clause uses de l'Unité A.
Une autre étape que vous pourriez envisager est l'installation d'une unité de la variable de B un pas de plus et l'avoir comme un appel de fonction pour un chargement à la demande, mais que cela peut aussi dépendre de votre utilisation.
par exemple
Je crois me souvenir de quelque part que l'unité d'initialisation peut être cher si un appareil que vous n'avez plus directement référence est toujours dans votre clause uses lors de la compilation, la puce de l'éditeur de liens ne sera pas enlever à cause de la section initialisation. Bien que cela puisse ne pas sembler mauvais que si chaque unité avait une section initialisation puis la plupart des programmes Delphi serait BEAUCOUP plus gros qu'ils ne le sont déjà.
Je ne dis pas ne pas les utiliser, mais ma règle d'or est de les utiliser avec parcimonie.
Votre premier exemple de code des pauses d'une règle. J'ai pensé que je le mentionne.
Ryan
J'utilise CnPack l'utilise plus propre. Il semble ignorer les unités qui ont de l'initialisation.
OriginalL'auteur Ryan J. Mills
Dans la situation que vous présentez ici, vous serez bien. Mais il ne serait pas beaucoup de refactoring avant que ça commence à aller mal.
Delphi fait un assez bon boulot pour s'assurer que les unités reste en mémoire tant qu'ils sont nécessaires. Mais il ne peut le faire s'il le sait une unité est nécessaire.
Mon exemple classique sur le thème est une unité qui ne contient qu'une liste d'objets
Part1 est uniquement explicitement à la personne à charge sur Contnrs. Delphi seulement d'assurer la Contnrs unité (et probablement aussi "subdependant" unités, même si je ne suis pas sûr à 100%) est toujours chargé en mémoire. Si TForm est ajouté dans la liste, les Formes de l'unité de ont déjà pu être finalisé lors de la
FList.free
est appelé, il va se planter quand il essaie de libérer la TForm qu'il contient. Delphi a aucun moyen de savoir Unit1 exige que les Formes de l'unité. Dans ce cas précis, il dépendra des unités de commande sont déclarées dans la rmr.OriginalL'auteur Ken Bourassa
Oui, c'est sûr. Vous pouvez simplifier le compilateur du travail en déclarant UnitB avant de l'UnitA dans la rmr de fichier, mais le compilateur va résoudre les références dans tous les cas.
OriginalL'auteur kludg
Dans l'esprit de la divulgation complète, je n'ai pas encore développé en Delphi depuis 2005. Cependant, j'ai développé en Delphi exclusivement de départ avec Delphi 1 en 1996, et a été certifié en Delphi 5 en 2001. Cela étant dit, mon utilisation de la finalisation de la section était rare. La seule fois où je l'utiliserais si j'avais besoin de mettre en place quelque chose de spécial .rmr. Que, généralement, ne s'est produite que si je faisais un composant personnalisé de développement, ET il y avait quelques dépendances que j'avais besoin de gérer à l'aide d'autres composants personnalisés j'étais en développement.
Typique pour le développement de l'application, je suis resté loin de l'initialisation/section finalisation et juste utilisé des modèles de conception comme des singletons, les façades et les usines de gérer la création et la gestion de mes classes. L'intégré dans le collecteur d'ordures a été assez bon pour 98,5% de mes projets.
Pour répondre à votre question, vous devez configurer une dépendance sur TFoo de l'UnitA dans votre code, et, comme Ryan a suggéré, assurez-vous qu'il est attribué avant la destruction. Cela étant dit, je vous encourage à vous assurer que l'utilisation de l'initialisation/section finalisation est nécessaire avant d'investir trop de temps avec elle.
L'affiche est très probablement référence à la CLASSIFICATION "Propriétaire" de comportement et/ou le fait que la mémoire pour les objets qui ne sont pas explicitement Libre avais est renvoyé dans le système lorsque le processus se termine, même si bien sûr, leurs destructeurs de ne pas exécuter.
Jim: Merci de me le rappeler...apparemment, l'exorcisme a été un succès complet. :o) Deltics: je me souviens d'avoir à utiliser FreeAndNil souvent pour libérer de la mémoire et le pointeur dans mon code pour les objets, j'ai créé dans le code, mais je ne voudrais pas utiliser la section initialisation à moins que je travaillais avec un système de ressources naturelles gérée, comme un objet COM. Même alors, il a été généralement associée avec des bibliothèques dépendantes ou de faire en sorte que les ressources étaient disponibles lors de mon composant commencé.
OriginalL'auteur Neil T.