![]() |
AddModuleUnloadProc und DEC
Hallo,
in der ![]()
Delphi-Quellcode:
Der registriert eine Prozedor ModuleUnload, die irgendwie beim Entladen eines Packages
Unit DECHashBase;
[..] procedure ModuleUnload(Instance: NativeInt); var // automaticaly deregistration/releasing i: Integer; begin if TDECHash.ClassList <> nil then begin for i := TDECHash.ClassList.Count - 1 downto 0 do begin if NativeInt(FindClassHInstance(TClass(TDECHash.ClassList[i]))) = Instance then TDECHash.ClassList.Remove(TDECFormat.ClassList[i].Identity); end; end; end; initialization AddModuleUnloadProc(ModuleUnload); TDECHash.ClassList := TDECClassList.Create; finalization RemoveModuleUnloadProc(ModuleUnload); TDECHash.ClassList.Free; end. aufgerufen wird, soweit ich die F1 Hilfe für AddModuleUnloadProc verstehe. In der ModuleUnload werden alle im globalen Klassenregistrierungsmechanismus der DEC (da kann man über eine ID den richtigen Algorithmus finden und eine Instanz davon erzeugen, sofern der Algorithmus in dieser TDECHash.ClassList registriert ist. Nun macht dieser ModuleUnload Code Ärger mit dem C++ Builder, der hat mit der Variable i da drin scheinbar irgend ein Problem. Die Frage für mich ist aber: wozu brauche ich den Code in ModuleUnload überhaupt? Reicht es nicht aus, dass ich diese Liste in finalization freigebe? Wenn diese Fragestellung geklärt ist, dürfte es auch zeitnah ein neues Rerlease 6.3 geben. Grüße TurboMagic |
AW: AddModuleUnloadProc und DEC
Bei deinem Problem kann ich dir nicht direkt helfen, mir ist nur aufgefallen, dass im Argument der Funktion TDECFormat statt TDECHash verwendet wird. Ist das wirklich korrekt?
Delphi-Quellcode:
TDECHash.ClassList.Remove(TDECFormat.ClassList[i].Identity);
|
AW: AddModuleUnloadProc und DEC
Hallo,
danke für die Meldung! Das ist natürlich falsch und wurde eben korrigiert, löst aber leider trotzdem meine eigentliche Problemstellung nicht. Grüße TurboMagic |
AW: AddModuleUnloadProc und DEC
Zitat:
Ja, es macht einen sehr großen Unterschied, ob du den Code vor dem Entladen des Moduls ausführst oder danach in finalization. In der Unload-Prozedur ist das Package noch nicht entladen, so dass es keine Probleme mit aus dem Hostprogramm in die Liste geschriebenen Klassen geben wird. Das finalization passiert aber erst danach (wo genau weiß ich aus dem Kopf bei Packages nicht), so dass es sein kann, dass es zu Fehlern bei der Freigabe dieser Objekte gibt. So ähnlich ist auch der Grund weshalb man Interfaces, die zwischen Hauptprogramm und DLL ausgetauscht wurden, vor dem Entladen der DLL auf nil setzen sollte, damit es beim Beenden der Anwendung keine Schutzverletzungen gibt. |
AW: AddModuleUnloadProc und DEC
Hallo,
danke schon mal für die Infos. Der Ärger ist: ich muss nur ein C++ Konsolenprogramm erstellen welches gar nichts tut, außer eine der Units die so einen Klassenregistrierungsmechanismus haben, einzubinden. Es reicht dafür die HPP Datei (en) zu generieren und die Unit selber ins Projekt aufzunehmen. Danach das mal ausführen und siehe da, beim Beenden crasht es in genau der Prozedure mit "Listeneintrag nicht gefunden". Der C++ Debugger zeigt, wenn man in der for Schleife einen Breakpoint setzt auch einen astronomisch hohen und nachgewiesen (mittels CPU Registeransicht) falschen Wert für i an. Und hier hört's für micht auf. Unter Delphi läuft das einfach durch, ohne Fehlermeldung. Kommentiert man die Routine aus, gibt's auch unter C++ Builder keine Fehlermeldung. Grüße TurboMagic |
AW: AddModuleUnloadProc und DEC
Ich nehme an TDECClassList war früher mal eine Liste (wahrscheinlich sogar TList wegen dem TClass-Cast). Im aktuellen Code ist die "Liste" nun ein TDictionary<Int64, TDECClass>. Der Code in ModuleUnload() geht aber weiterhin davon aus, dass es sich um eine TList handelt, deren Items TClass sind. Aber wegen dem Dictionary wird die for-Variable "i" nun nicht mehr als Index in die Liste verwendet sondern als Key ins Dictionary. Und das löst die Fehlermeldung aus, da es wahrscheinlich keinen Eintrag mit Key=0, Key=1 usw. gibt.
Dass es unter Delphi funktioniert und unter C++Builder nicht, liegt daran, dass C++Builder ModuleUnload() auch für das eigene Modul aufruft und Delphi eben nicht. Somit fällt der Fehler unter einem "DLL/BPL-freiem" Delphi nicht auf. Als erstes würde ich die erste If-Anweisung um "if (Instance <> HInstance) and ..." erweitern. Der Aufruf mit der eigenen HInstance der Unit ist nutzlos, da im finalization sowie die Liste freigegeben wird. Wenn also die Unit aus dem eigenen Modul (DLL, BPL) entladen wird, muss nicht noch unnötige Extra-Arbeit geleistet werden. Das behebt den "Index vs Key" Fehler aber noch nicht. Hierfür muss das Dictionary als Dictionary behandelt werden:
Delphi-Quellcode:
procedure ModuleUnload(Instance: NativeInt);
var // automaticaly deregistration/releasing i: Integer; Items: TArray<TPair<Int64, TDECCLass>>; begin // C++Builder calls this function for our own module, but we destroy the ClassList in that case in the finalization section anyway. if (Instance <> HInstance) and (TDECHash.ClassList <> nil) and (TDECHash.ClassList.Count > 0) then begin Items := TDECHash.ClassList.ToArray; for i := Length(Items) - 1 downto 0 do begin if FindClassHInstance(Items[i].Value) = HINST(HInstance) then TDECHash.ClassList.Remove(Items[i].Key); end; end; end; Derselbe Fehler ist übrigens auch in - DECCipherBase.pas - DECFormatBase.pas - DECHashBase.pas (hier beschriebener Fehler) |
AW: AddModuleUnloadProc und DEC
Hallo,
danke für die wertvollen Infos/Tipps. Werde das baldmöglichst so umsetzen und testen. Grüße TurboMagic |
AW: AddModuleUnloadProc und DEC
Es gibt davon auch eine Prozedur mit NativeUInt Parameter.
Die würde ich gerne lieber nutzen um eine Warnung wegen Vergleich int zu unit zu vermeiden. Wäre das OK und seid wann gibt es diese? |
AW: AddModuleUnloadProc und DEC
In Delphi 2009 gibt es die bereits, wobei dort noch als "(HInstance: LongWord)". In Delphi XE ist es dann schon "(HInstance: THandle)".
Eine explizite "NativeUInt" Version gibt es nicht. Jedoch ist unter Delphi 2009 "THandle = LongWord" und unter Delphi XE "THandle = NativeUInt". Somit sollte die "HInstance: THandle" deklaration in allen Delphis ab 2009 (und vielleicht sogar 2006/2007) funktionieren. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:59 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz