| Autor |
Beitrag |
Ratchet
      
Beiträge: 63
Windows7 x86
D5 Ent., D2006 Arch.
|
Verfasst: Mo 28.09.09 10:26
Ich habe ein Programm welches selbstgeschriebene DLLs dynamisch läd. Funktioniert auch alles prima, nur wenn ich das Programm ändere hängt es sich auf. Dort wo die DLLs wieder entladen werden sollen.
Ich habe eine Array (PluginList) in dem Objekte mit den Handles der DLLs gemerkt werden. Beim Beenden gehe ich nur dieses Array durch und möchte mit FreeLibrary alles schön sauber machen. Momentan habe ich zwei DLLs geladen. Die erste wird auch normal mit FreeLibrary abgearbeitet, aber bei der zweiten geht dann nichts mehr. Dachte erst irgendwann würde eine Überlauf passieren, habe das Programm also einfach mal laufen lassen, aber den ganzen Tag lang ist nichts passiert. Das Hostprogramm sowie die DLLs sind mit ShareMem und Laufzeitpackages übersetzt.
Jemand eine Idee was das sein könnte?
Pausiere ich das Programm erscheint das CPU Fenster beim Befehl
Quelltext 1: 2:
| ntdll.KiFastSystemCallRet: 77A95E74 C3 ret |
So entlade ich die DLLs
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| procedure UnloadAllPlugins; var i: Integer; begin for i := Length(PluginList) - 1 downto 0 do begin FreeAndNil(PluginList[i].ccsPlugin); if PluginList[i].DllHandle <> 0 then begin FreeLibrary(PluginList[i].DllHandle); end; FreeAndNil(PluginList[i]); end; SetLength(PluginList, 0); end; |
_________________ So long, and thank's for all the fish
<°))))><>
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mo 28.09.09 12:38
hast du die Schleife schon mal debuggt und bist sie in Einzelschritten durchgegangen, um zu gucken, ob die Werte stimmen?
|
|
Ratchet 
      
Beiträge: 63
Windows7 x86
D5 Ent., D2006 Arch.
|
Verfasst: Mo 28.09.09 13:04
Ja, stimmt alles. Also alles was ich mir so ansehen kann sieht vernünftig aus. Die Objekte stimmen, Handle von den DLLs sind immer noch die gleichen wie nach dem Laden.
_________________ So long, and thank's for all the fish
<°))))><>
|
|
HelgeLange
      
Beiträge: 735
Erhaltene Danke: 6
Windows 7
Delphi7 - Delphi XE
|
Verfasst: Mo 28.09.09 16:44
Bist Dir sicher, dass in der DLL alles freigegeben wird ? ändere mal die reihenfolge, in welcher du die DLL lädst und entlädst und schau, ob es an einer bestimmten DLL hangt oder es immer die 2. ist
_________________ "Ich bin bekannt für meine Ironie. Aber auf den Gedanken, im Hafen von New York eine Freiheitsstatue zu errichten, wäre selbst ich nicht gekommen." - George Bernhard Shaw
|
|
Tryer
      
Beiträge: 226
Erhaltene Danke: 7
|
Verfasst: Mo 28.09.09 20:10
Gibt es ein Handshake mit dem "cssPlugin" und wartet die dll noch auf irgendwas? Ggf. also die Free - Reihenfolge cssPlugin / dll anpassen.
|
|
Ratchet 
      
Beiträge: 63
Windows7 x86
D5 Ent., D2006 Arch.
|
Verfasst: Di 29.09.09 09:52
@HelgeLange: In den DLLs wird alles freigegeben, habe ich eben nochmal Schritt für Schritt geprüft. Die Reihenfolge des Ladens und Entladens habe ich auch mal geändert. Es ist immer ab der zweiten DLL, egal welche von beiden es ist. Irgendwas scheint da zu passieren.
@Tryer: Einen Handshake gibt es nicht. Das Free der DLLs und des csPlugins kann ich nicht ändern. Wenn ich das ccsPlugin nach der DLL lösche (FreeAndNil) dann bekomme ich eine Zugriffsverletzung. Ist auch logisch, denke ich, da ich ja keinen Zugriff mehr auf die DLL habe.
_________________ So long, and thank's for all the fish
<°))))><>
|
|
Flamefire
      
Beiträge: 1207
Erhaltene Danke: 31
Win 10
Delphi 2009 Pro, C++ (Visual Studio)
|
Verfasst: Di 29.09.09 11:18
wie ist denn die deklaration des arrays? hängt er wirklich beim freelibrary oder möglicherweise schon eher?
|
|
Ratchet 
      
Beiträge: 63
Windows7 x86
D5 Ent., D2006 Arch.
|
Verfasst: Di 29.09.09 11:51
Ja wirklich beim FreeLibrary. Das Array ist folgendermnaßen deklariert, das Laden der DLLs habe ich auch mal mit rangehängt:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56:
| type TDllPlugin = class ccsPlugin: TccsPlugin; DllFile: string; DllHandle: THandle; end;
TPluginList = array of TDllPlugin;
TccsPluginInitProcedure = function(DBConnection: TADOConnection): TccsPlugin; stdcall;
var PluginList: TPluginList;
implementation
function LoadPlugins(Mask: string): Integer; var InitFunction: TccsPluginInitProcedure; i: Integer; sr: TSearchRec; begin Result := 0; if FindFirst(DllPath + Mask, faAnyFile, sr) = 0 then begin repeat SetLength(PluginList, Length(PluginList) + 1); PluginList[Length(PluginList) - 1] := TDllPlugin.Create; PluginList[Length(PluginList) - 1].DllFile := DllPath + sr.Name; PluginList[Length(PluginList) - 1].DllHandle := LoadLibrary(PAnsiChar(DllPath + sr.Name)); InitFunction := GetProcAddress(PluginList[Length(PluginList) - 1].Dllhandle, 'Init'); if Assigned(InitFunction) then begin PluginList[Length(PluginList) - 1].ccsPlugin := InitFunction(ccsGlobalDataConnection); Inc(Result); end; until FindNext(sr) <> 0; SysUtils.FindClose(sr); end; end;
procedure UnloadAllPlugins; var i: Integer; begin for i := Length(PluginList) - 1 downto 0 do begin FreeAndNil(PluginList[i].ccsPlugin); if PluginList[i].DllHandle <> 0 then begin FreeLibrary(PluginList[i].DllHandle); end; FreeAndNil(PluginList[i]); end; SetLength(PluginList, 0); end; |
_________________ So long, and thank's for all the fish
<°))))><>
|
|
Flamefire
      
Beiträge: 1207
Erhaltene Danke: 31
Win 10
Delphi 2009 Pro, C++ (Visual Studio)
|
Verfasst: Di 29.09.09 15:29
ok allgemein: solche sachen gehören in den constructor und destructor der klasse
wenn du schon ein objekt hast, warum benutzt du dann create/destroy nicht?
geht viel sauberer
2: statt findfirst benutze lieber fielexists
3: für dein problem: versuche es mal testweise so:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| procedure UnloadAllPlugins; var i: Integer; begin for i := Length(PluginList) - 1 downto 0 do begin if PluginList[i].DllHandle <> 0 then begin FreeLibrary(PluginList[i].DllHandle); end; end; SetLength(PluginList, 0); end; |
und danach so:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| procedure UnloadAllPlugins; var i: Integer; begin for i := Length(PluginList) - 1 downto 0 do begin if PluginList[i].DllHandle <> 0 then begin FreeLibrary(PluginList[i].DllHandle); end; FreeAndNil(PluginList[i]); end; SetLength(PluginList, 0); end; |
BTW: wenn du die initfunktion iwo benutzt: kommentier den teil mal aus, um zu prüfen, obs ohne die initfunktion korrekt funktioniert
|
|
Ratchet 
      
Beiträge: 63
Windows7 x86
D5 Ent., D2006 Arch.
|
Verfasst: Di 29.09.09 16:47
Flamefire hat folgendes geschrieben : | ok allgemein: solche sachen gehören in den constructor und destructor der klasse
wenn du schon ein objekt hast, warum benutzt du dann create/destroy nicht?
geht viel sauberer |
Stimmt. Ist anscheint historisch so gekommen, habe es geändert.
Und egal ob mit oder ohne Init, und auch wenn ich die FreeAndNils weglasse, selbes Verhalten.
_________________ So long, and thank's for all the fish
<°))))><>
|
|
HelgeLange
      
Beiträge: 735
Erhaltene Danke: 6
Windows 7
Delphi7 - Delphi XE
|
Verfasst: Di 29.09.09 16:59
lädst Du Laufzeitpackages dynamisch ? also vcl.bpl, rtl, vcldb, rtldb und wie sie alle heissen ?
Du scheinst ein Object aus der DLL in deinem Unload freizugeben, wenn Du allerdings nichts mit Laufzeit-Packages arbeitest, haben Hauptprogramm und DLL alle eigene VCL variablen etc.
_________________ "Ich bin bekannt für meine Ironie. Aber auf den Gedanken, im Hafen von New York eine Freiheitsstatue zu errichten, wäre selbst ich nicht gekommen." - George Bernhard Shaw
|
|
Tryer
      
Beiträge: 226
Erhaltene Danke: 7
|
Verfasst: Di 29.09.09 18:15
Hinweis aus dem MSDN bzgl. DllMain | Zitat: | Calling functions that require DLLs other than Kernel32.dll may result in problems that are difficult to diagnose. For example, calling User, Shell, and COM functions can cause access violation errors, because some functions load other system components. Conversely, calling functions such as these during termination can cause access violation errors because the corresponding component may already have been unloaded or uninitialized.
Because DLL notifications are serialized, entry-point functions should not attempt to communicate with other threads or processes. Deadlocks may occur as a result.
For information on best practices when writing a DLL, see www.microsoft.com/wh...el/DLL_bestprac.mspx. |
|
|
HelgeLange
      
Beiträge: 735
Erhaltene Danke: 6
Windows 7
Delphi7 - Delphi XE
|
Verfasst: Di 29.09.09 18:31
Aber keine Sorge, das mit den DLLs funnktioniert und auch die DB-Verbindung, die du dahin übergeben willst.
Ich nutze ähnliches in meinem Komponenten-Package seit Jahren ohne Probleme.. naja, es gibt manchmal Zeiten wo es beim entyladen crasht, das liegt aber dadran, dass ich was essentielles ändern musste, was das Entladen beinflusste. Hatte erst gestern 2 Stunden einen solchen Fehler gesucht, der lag allerdings auch wirklich in meinen Komponenten...
Lass Dich also nicht entmutigen.
Zur Not poste doch mal ein komplettes lauffähiges Programm mit source, dann helf ich Dir debuggen
_________________ "Ich bin bekannt für meine Ironie. Aber auf den Gedanken, im Hafen von New York eine Freiheitsstatue zu errichten, wäre selbst ich nicht gekommen." - George Bernhard Shaw
|
|
Ratchet 
      
Beiträge: 63
Windows7 x86
D5 Ent., D2006 Arch.
|
Verfasst: Do 01.10.09 08:02
_________________ So long, and thank's for all the fish
<°))))><>
|
|