![]() |
DLL mit Runtime-Packages: Entladehemmung!?
Hallo,
Die Architektur unseres Projekts besteht aus einer Exe-Datei und dynamisch ladbaren Dlls. Bei der Umstellung von Delphi 4 auf Delphi 2006 treten nun verstärkt Probleme mit dem is - Operator auf, so daß wir eine Alternative suchen. Die Verwendung von Runtime-Packages in der Exe sowie den Dlls für alle Borland- und Zukauf-Units bewirkt, daß die Anwendung zufriedenstellend läuft, beim Schließen wird sie aber nicht mehr entladen, sobald 2 Dlls mit Runtime-Packages geladen wurden. Bei Verwendung des LCPI-OLE DB Providers für Firebird tritt zusätzlich in einer zugehörigen DLL eine Schutzverletzung auf. Wir haben schon darauf geachtet, das jedes LoadLibrary durch ein FreeLibrary und jedes CoInitialize durch ein CoUnInitialize aufgehoben wird. Gibt es noch etwas, worauf wir achten müssen oder müssen wir unsere DLLs komplett zu dynamisch zu ladenden Runtime-Packages umbauen ? Über einen Hinweis würden wir uns freuen. |
Re: DLL mit Runtime-Packages: Entladehemmung!?
Der is Operator basiert auf den RTTI-Daten. Eine Delphi-DLL hat nicht nur einen eigenen Memory-Manager, sondern daraus folgend auch eigene RTTI-Daten. is kann also schiefgehen. ShareMem verbindet die Memory-Manager. Soweit ich weiss muss aber noch mehr getan werden, damit das RTTI auch laeuft. Genau diese Zusatzleistungen erbringt das Package.
|
Re: DLL mit Runtime-Packages: Entladehemmung!?
Das Nichtfunktionieren des is - Operators aufgrund unschiedlicher RTTI-Objekte lässt sich auch schön im Debugger verfolgen. Das darufhin erzielte Ergebnis ist auch eindrucksvoll: "TFont ist nicht vom Typ TFont".
Deshalb nutzten wir die Runtime-Packages, geraten aber nun mit unseren DLL's vom Regen in die Traufe: Eine von ihnen lässt sich schön laden und entladen, bei der zweiten knallts am Programmende. In Kürze das was ich über das Problem weiss: - Es reicht, eine zweite DLL zu laden und sofort zu entladen: Knall!! - vollkommen entleerte DLL laden und entladen: dito - wo knallt es: verantwortlich ist der Handlungsstrang nach ExitProcess (_Halt0 in system.pas). FinalizeUnits läuft also noch ohne Probleme durch - verantwortlich scheinen die OLE-DB-Treiber zu sein. Je nach verwendeter DB (Firebird oder Oracle) werden unterschiedliche Fehler kredenzt. - im Speicher bleiben Objekte vom Typ AdoDB.asyncEventMessenger stehen; gilt für beide DB's Verzichte ich auf Runtime-Packages, bleiben die Fehler aus. Alternativ: Vielleicht weiss jemand, wie sich RTTI-Barrieren tunneln lassen?? |
Re: DLL mit Runtime-Packages: Entladehemmung!?
Euer Problem ist das eure Lösung unter Delphi 4 funktionierte obwohl dort die gleichen Probleme vorliegen, jedoch zufälligerweise nicht die Probleme verursacht hat.
Falls es die OLE DB-Provider sind: Wird hier u.U. "versehentlich" CoInitialize im finalization einer Unit aufgerufen? Ansonsten: Was stört es wenn die BPL's geladen bleiben. So viel mehr an Speicher wird wohl nicht verbraten. |
Re: DLL mit Runtime-Packages: Entladehemmung!?
Ohne Zweifel: Delphi4 hat einiges unter dem Mantel der Verschwiegenheit verschwinden lassen, was jetzt hochkommt.
Leider ist es nicht damit getan, dass die Anwendung nicht sauber beim Betriebssystem ausgetragen wird. Nachfolgende Aufrufe reagieren in der Oracle-Version sehr ungehalten auf die herumliegenden Trümmer des Vorgängers und stellen die Mitarbeit ein. Unter Firebird wird am Ende zwar erfolgreich aufgeräumt, aber erst nach 3 mit Tamm-Tamm veröffentlichten Exceptions. Wenn die Kunden nicht so pingelig wären, ... Vielen Dank zum Hinweis auf das fehlplazierte CoInitialize. Wie werden suchen. |
Re: DLL mit Runtime-Packages: Entladehemmung!?
Ich würde für Oracle und Firebird eh keine ADO-Basierenten DB-Zugriff nehmen. Dafür gibt es direktere Möglichkeiten. U.a. auch welche die z.B. keinen installierten Oracle-Client benötigen.
|
Re: DLL mit Runtime-Packages: Entladehemmung!?
Wenn schon die finalization sections geprueft werden, dann sollte man dort alle globalen Variablen sauber zuruecksetzen, also FreeAndNil verwenden bzw. analoges Ruecksetzen. Das hat uns bei den JVCL Packages in der IDE immer Probleme bereitet bis wir es ausgemistet hatten.
|
Re: DLL mit Runtime-Packages: Entladehemmung!?
Die JVCL ist bei uns auch im Einsatz. Danke für den Hinweis! Ich fang mal an zu graben.
|
Re: DLL mit Runtime-Packages: Entladehemmung!?
Lösung gefunden: Problem liegt in der aktuellen Sharemem-Implementierung: Problembeschreibung und -lösung findet sich unter:
![]() |
Re: DLL mit Runtime-Packages: Entladehemmung!?
Hallo,
Eventuell lohnt ja ein Umstieg auf FastMM4 - dort wird auch eine FastMM4-Version der borlndmm.dll mitgeliefert. Hätte auch den Vorteil, dass FastMM4 schneller ist. mfG mirage228 |
Re: DLL mit Runtime-Packages: Entladehemmung!?
Wenn du ladbare DLLs mit Packages kombinierst dann müssen gewissen Regeln eingehalten werden:
1.) alle DLLs müssen Packages benutzen, und zwar alle Packages die benötigt werden 2.) niemals ShareMem oder FastMM oä. benutzen das ist absolut unnötig und fehleranfällig. Da alle Objekte über die RTL und damit über das System-Package alloziert werden hat man in diesem Moment sowieso einen gemeinsam benutzten Memory Manager, auch ohne ShareMem ! 3.) alle gemeinensam zu benutzenden Klassen gehören in Packages 4.) alle "unsichtbaren" Klassen wie die speziellen Formulare, Reporte usw. können in den DLLs verbleiben. Der Aufruf von is und as auf solche "privaten" DLL-Klassen muß dann ein Vergleich mit der in Packages implementierten Vorfahrklassen sein. Also zb. Self is TForm oder Self is TCustomForm, aber nicht Form12 is TDLL_Form15 wobei Form12 zb. in DLL_12 und die Klasse TDLL_Form15 in DLL15 implementiert wurde. Somit gilt: die Packages stellen eine gemeinsam benutzten Brückenkopf zwischen den nachladbaren und privaten Endstellen in Form einer DLL dar. Dann musst du sehr genau überprüfen welche 3'rd Party Packages du einbindest. Sehr oft haben deren Entwiker nicht berücksichtigt das deren Packages eben auch zur Laufzeit geladen und entladen werden können. Zb. Report Builder oder QuickReport. Beispiel: Hauptanwendung ist 34kB große EXE und lädt ein allgemeines TMainForm aus einem Package "Main" für die Anwendung. Diese EXE importiert aber eben nicht statisch schon die Report Packages. Erst wenn über das TMainForm eine DLL geladen wird, zb. ein Report in einer DLL, werden in diesem Moment auch alle zusätzlichen Packages für diese DLL nachgeladen. Wird nun der Report freigegeben und daraufhin diese DLL wieder entladen so werden auch diese Packages autom. wieder entladen. Nun benutzen aber einige der Komponenten in solchen Packages globale Hooks, zb. Application.OnMessage() als Events. Diese werden meistens in der Initialization/Finalization Sektion einer Unit installiert und wieder deinstalliert (wenn überhaupt deinstalliert wird). Sowas bringt massive Probleme mit sich. Einfach weil die Entwickler dieser Komponenten nicht daran gedacht haben das ihre Packages nicht statisch sondern dynamisch geladen und eben auch wieder entladen werden. Abhilfe ist es dann in der Main.EXE der Anwendung diese Packages sofort und einmalig nachzuladen, oder aber die Formular/Report-DLLs einmal geladen nicht wieder zu entladen. Die Sache ist also: entweder mit Packages arbeiten und dann aber richtig und absolut konsequent oder erst garnicht damit anfangen. Alle nachladbaren Module in DLLs packen, aber mit dem Hintergedanken das deren darin implementierten Klassen absolut privat sind. Das ist sogar von Vorteil da man so mit sauberen Schnittstellen Modulübergreifend arbeiten muß und einer striktere Modularisierung entsteht. Gruß Hagen |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:53 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