AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

AddModuleUnloadProc und DEC

Ein Thema von TurboMagic · begonnen am 7. Aug 2021 · letzter Beitrag vom 10. Aug 2021
Antwort Antwort
TurboMagic

Registriert seit: 28. Feb 2016
Ort: Nordost Baden-Württemberg
2.942 Beiträge
 
Delphi 12 Athens
 
#1

AddModuleUnloadProc und DEC

  Alt 7. Aug 2021, 16:07
Hallo,

in der DEC (die ich ja "geerbt" habe) ist folgender Code drin:

Delphi-Quellcode:
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.
Der registriert eine Prozedor ModuleUnload, die irgendwie beim Entladen eines Packages
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
  Mit Zitat antworten Zitat
shebang

Registriert seit: 7. Feb 2020
124 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: AddModuleUnloadProc und DEC

  Alt 8. Aug 2021, 00:54
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?

TDECHash.ClassList.Remove(TDECFormat.ClassList[i].Identity);
  Mit Zitat antworten Zitat
TurboMagic

Registriert seit: 28. Feb 2016
Ort: Nordost Baden-Württemberg
2.942 Beiträge
 
Delphi 12 Athens
 
#3

AW: AddModuleUnloadProc und DEC

  Alt 8. Aug 2021, 11:15
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
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.582 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: AddModuleUnloadProc und DEC

  Alt 8. Aug 2021, 15:13
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?
Die Frage ist wie sich dieser Ärger äußert. Vielleicht lässt sich das ja korrigieren.

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.
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
TurboMagic

Registriert seit: 28. Feb 2016
Ort: Nordost Baden-Württemberg
2.942 Beiträge
 
Delphi 12 Athens
 
#5

AW: AddModuleUnloadProc und DEC

  Alt 8. Aug 2021, 15:42
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
  Mit Zitat antworten Zitat
jbg

Registriert seit: 12. Jun 2002
3.483 Beiträge
 
Delphi 10.1 Berlin Professional
 
#6

AW: AddModuleUnloadProc und DEC

  Alt 8. Aug 2021, 19:59
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)

Geändert von jbg ( 8. Aug 2021 um 20:04 Uhr)
  Mit Zitat antworten Zitat
TurboMagic

Registriert seit: 28. Feb 2016
Ort: Nordost Baden-Württemberg
2.942 Beiträge
 
Delphi 12 Athens
 
#7

AW: AddModuleUnloadProc und DEC

  Alt 9. Aug 2021, 09:19
Hallo,

danke für die wertvollen Infos/Tipps.
Werde das baldmöglichst so umsetzen und testen.

Grüße
TurboMagic
  Mit Zitat antworten Zitat
TurboMagic

Registriert seit: 28. Feb 2016
Ort: Nordost Baden-Württemberg
2.942 Beiträge
 
Delphi 12 Athens
 
#8

AW: AddModuleUnloadProc und DEC

  Alt 10. Aug 2021, 19:12
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?
  Mit Zitat antworten Zitat
jbg

Registriert seit: 12. Jun 2002
3.483 Beiträge
 
Delphi 10.1 Berlin Professional
 
#9

AW: AddModuleUnloadProc und DEC

  Alt 10. Aug 2021, 21:22
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.
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:52 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz