Jetzt ist es mal wieder soweit das ich zum zweiten mal in kurzer Zeit auf das selbe Problem mit runtime Packages stoße.
Situation ist folgende:
- Anwendung die verschiedene Module als DLL lädt (kompletter Datenaustausch über Interfaces)
- Verschiedene runtime packages werden verwendet, unter anderem VCL, RTL (ohne Probleme). Grund dafür ist zum einem die Verringerung der binary Größe und zum anderem das umgehen bestimmter Limitierungen beim Datenaustausch zwischen Host Anwendung und DLL
- Problem ist wenn nun andere third Party Komponenten verwendet werden. Konkrete Probleme gibt es hier mit JVCL (auch ohne extra JVCL runtime package) und mit Graphics32 (als extra Graphics 32 runtime package)
- Problem ist das die third Party Komponenten diverse globale Units mit finalization Blöcken haben die aufgrund der Verwendung mit runtime packages mehrfach aufgerufen werden (von jeder DLL die die Unit verwendet und von der Anwendung selbst)
- Aufgrund der runtime packages dürfte der finalization block pro Unit jedoch nur einmal aufgerufen werden (nicht mehrfach für jede DLL/Anwendung). Da er mehrfach aufgerufen wird gibts dann den alt bekannten Runtime Error 216 nach beenden der Anwendung. Der genaue grund ist die Zugriffsverletzung im mehrfach aufgerufenem finalization block der globalen units.
Die Frage ist jetzt ob ich das ganze umgehen kann OHNE die ganzen finalization Blöcke der third party units umzuschreiben (also ohne entsprechende nil checks einzubauen).
Hier noch ein konkretes Beispiel:
Delphi-Quellcode:
unit GR32_System.pas;
[...]
var
GlobalPerfTimer: TPerfTimer;
[...]
implementation
[...]
initialization
[...]
GlobalPerfTimer := TPerfTimer.Create;
finalization
GlobalPerfTimer.Free;
[...]
Aufgrund der Verwendung von Graphics32 als runtime packages teilen sich all dlls und die host anwendung die gleiche
Unit und damit die gleiche Variable GlobalPerfTimer. Trotzdem wird der finalization block beim beenden für jede einzelne
dll aufgerufen (lustigerweise wird der initialization block nur einmal ausgeführt). Das erste mal geht das natürlich gut, beim zweitem Aufruf des finalization blocks wurde die variable natürlich schon freigegeben und die entsprechende
Access Violation folgt.
Einfache lösung wäre natürlich das ganze umzuschreiben in
(noch nicht getestet, aber ich geh mal davon aus das das gehen sollte)
Delphi-Quellcode:
[...]
finalization
if GlobalPerfTimer <> nil then
begin
GlobalPerfTimer.Free;
GlobalPerfTimer := nil;
end;
[...]
Das würde ich aber vermeiden wollen da ich ungern third Party units modifiziere (wenn es sich nicht vermeiden läßt) und das gerade bei JVCL in viel arbeit ausartet (bei JVCL tritt das Problem mit der lustigen uxtheme
dll auf weil die xp theming klasse mehrfach freigeben wird).
Aktuell suche ich noch verzweifelt nach einer möglichkeit das irgendwie anders zu lösen. Konnte aber im Netz bisher nichts brauchbares zu finden (mal von den "hilfe ich krieg einen runtime 216 error beim beenden meiner Anwendung, warum???" beiträgen abgesehen
)
Deshalb auch dieser etwas ausführlichere Beitrag, ich hoffe irgendwer hat eine Idee wie man das ganze ohne umschreiben der finalization blöcke lösen könnte.