![]() |
Re: Problem beim Beenden (DLL mit Formular und mODBC)
Hallo!
Ich habe jetzt noch folgendes herausgefunden: Wenn ich das Formular so
Delphi-Quellcode:
oder so
Form1:=TForm1.Create(Application);
Delphi-Quellcode:
erzeuge, dann wird beim schließen von Form1 nicht nur die DLL (bzw. das Form1) sondern auch die Anwendung, die die DLL aufgerufen hat beendet.
Application.CreateForm(TForm1, Form1);
=> Offensichtlich steht in der Variablen "Application" die Referenz, auf das Programm, dass die DLL aufgerufen hat. Scheinbar verwenden die Komponenten (inklusive mODBC) dann dieses Application-Objekt. Das scheint ein grundsätzliches Problem zu sein. Ich gehe davon aus, dass es kein Problem geben würde, wenn die DLL ein eigenes Application-Objekt hätte. Gibt es hier jemanden, der sich damit auskennt, oder soll ich einen separaten Thread in einer anderen Rubrik starten? Gruß, StTüff |
Re: Problem beim Beenden (DLL mit Formular und mODBC)
<offtopic>
Zitat:
Weniger Zeilen machen dein Programm lesbarer! </offtopic> |
Re: Problem beim Beenden (DLL mit Formular und mODBC)
Zitat:
Dann schau dir mal den Source an (Delphi2007Prof) von SysUtils.pas:
Delphi-Quellcode:
Da ist keine Abfrage nach assigend! :angel:
procedure FreeAndNil(var Obj);
var Temp: TObject; begin Temp := TObject(Obj); Pointer(Obj) := nil; Temp.Free; end; Deshalb möglicher eigener Ersatz: (aber natürlich "langsamer")
Delphi-Quellcode:
procedure MyFreeAndNil(var Obj);
var Temp: TObject; begin Temp := TObject(Obj); Pointer(Obj) := nil; if assigned(Temp) then Temp.Free; end; |
Re: Problem beim Beenden (DLL mit Formular und mODBC)
Zitat:
|
Re: Problem beim Beenden (DLL mit Formular und mODBC)
OK. Nach dem wir das geklärt haben noch mal zu meinem Problem:
Ich fasse zusammen: - Beim Starten des Programms (das die DLL aufruft; statische Bindung) wird von mODBC der Initializeabschnitt ausgeführt (nicht beim create des Formulars). - Der Finalizeabschnitt entsprechend beim Beenden und nich beim free des Formulars. - Ist das Formular bereits freigegeben gibt es eine Exception (ungültiger Speicherzugriff). Wird das Formular nicht freigegeben gibt es kein Problem (abgesehen davon dass das Formular dann nicht freigegeben ist). - Frage ich in der DLL "application.exename" ab so wird mir der Name der Aufrufenden Anwendung ausgegeben. - Bei anderen Parametern (z.B. "application.mainForm") gibt es in der DLL eine Fehlermeldung in der EXE kann zugegriffen werden. => application ist also offensichtlich nicht identisch, hat aber Einfluss auf die Komponenten auf dem DLL-Formular (Verwendung von Application in mODBC). - Gebe ich beim erzeugen des Formulars apllication als Parent an, so wird das Formular automatisch zerstört, die Fehlermeldung kommt aber trotzdem.... Alles schön zusammengefasst, aber immer noch keine Ahnung.... :pale: Kann das jemand nachvollziehen? Soll ich noch weitere Quellen (mODBC) oder sonst was hochladen? Gruß und vielen Dank für die Unterstützung, StTüff |
Re: Problem beim Beenden (DLL mit Formular und mODBC)
Hallo
@stTüff: Hast du meine Absicherung mal eingebaut? Sorry stTüff aber die Discussion mit Flocke ist auch für dich wichtig! Meiner Meinung nach kann hier Dir am schnellesten geholfen werden. @Flocke: Okay, Tobject.Free ist abgesichert, aber was ist mit den Nackommen? :twisted: In den meisten Fällen arbeiten wir mit Erben von TObject. Sobald diese etwas mehr im Free/Destroy machen könnte in manchen Situation der Vorschlag von mir helfen. Denn da fehlt meistens die Assigned oder NIL-Abfrage... Ein Beispiel original Code:
Delphi-Quellcode:
Mein grundsätzlicher Vorschlag ist, daß es EXACT eine Variable gibt, welche den Zeiger auf ein dynamisch angelegtes Object oder Speicherbereich enthält. Wenn diese Variable einen Wert<>NIL beinhaltet, dann existiert das Object/Speicherbereich. Wenn diese Variable NIL beinhaltet, dann wurde es von mir auch wieder freigegeben! Natürlich kann es Kopien dieses Zeigers geben, aber es sollte immer klar sein, was ist die Referenz und was die Kopie.
destructor TCustomForm.Destroy;
begin Application.RemovePopupForm(Self); if not (csDestroying in ComponentState) then GlobalNameSpace.BeginWrite; try if OldCreateOrder then DoDestroy; MergeMenu(False); if HandleAllocated then DestroyWindowHandle; Screen.RemoveForm(Self); FCanvas.Free; FIcon.Free; FreeAndNil(FPopupChildren); FreeAndNil(FRecreateChildren); GlassFrame.Free; FreeMem(Pointer(FPixelsPerInch)); inherited Destroy; finally GlobalNameSpace.EndWrite; end; end; |
Re: Problem beim Beenden (DLL mit Formular und mODBC)
Na klar habe ich die "Sicherung" eingebaut (war in meinem eigentlichen Projekt übrigens schon immer so, nur eben in dem vereinfachten Beispiel nicht).
Leider macht das keinen Unterschied. Es ist auch nicht so, dass der Fehler beim Destroy des Objektes auftritt. Vielmehr passiert beim finalize von mODBC irgendwas, was ich noch nicht näher eingrenzen konnte. Momentan geht meine Vermutung wie oben erwähnt dahin, dass es etwas mit dem application-Objekt (bzw. mit den Unterschieden bei dem Objekt zwischen DLL und EXE) zu tun hat. Kann aber auch sein, dass ich da voll auf dem Holzweg bin. Sicher ist nur, dass nicht mehrfach versucht wird Form1 freizugeben. Allerdings ist ebenfalls sicher, wenn Form1 nicht freigegeben wird, tritt keine Fehlermeldung auf und Form1 wird definitiv nicht freigegeben (OnDestroy tritt dann nicht ein). Ich komme einfach nicht so richtig weiter. Habe nur ich das Problem? Vermutlich ja: Sonst macht keiner was mit DLL und Forms, weil es da nur Probleme gibt, oder? Vielleicht kann mir jemand eine Alternative nennen. Voraussetzung ist, dass der Aufruf der Funktione aus einer beliebigen Programmier-/Scriptsprache erfolgen kann (z.B. VBA). Gruß, StTüff |
Re: Problem beim Beenden (DLL mit Formular und mODBC)
@StTüff: Der Fehler tritt offensichtlich in TmSession.FreeHENV beim Aufruf von SQLFreeHandle auf. Da läuft offensichtlich irgendetwas schief, was du schlecht beeinflussen kannst. Als ganz bösen Workaround kannst du die Zeile "SQLFreeHandle" in TmSession.FreeHENV in try..except klammern und den Fehler ignorieren:
Delphi-Quellcode:
@peschai:
procedure TmSession.FreeHENV;
begin if FHENV = 0 then exit; try SQLFreeHandle(SQL_HANDLE_ENV, FHENV); except end; FHENV:=0; end; Zitat:
Den virtuellen Destruktor destructor Destroy, 1. den man in eigenen Klassen überschreiben kann, 2. der immer mit einem Aufruf von inherited; enden sollte und 3. den man nie direkt aufrufen sollte. Die statische Methode procedure Free, die 1. man nie überschreiben sollte, 2. als einzige (letzendlich) nutzen sollte, um ein Objekt freizugeben und 3. die eben aus dem Grund existiert, dass sie prüfen kann ob "Self <> nil" ist - eine virtuelle Methode kann das nämlich nicht. Darum reicht FreeAndNil! Den Zeiger vorher auf NIL zu prüfen ist überflüssig. |
Re: Problem beim Beenden (DLL mit Formular und mODBC)
Hallo Flocke!
Danke für die Info! Da bin ich auf der einen Seite froh, dass ich nicht ganz auf dem Holzweg war, andererseits traurig, dass es keine "perfekte" Lösung gibt. Die Frage, die jetzt noch bleibt: Ist es besser das Formular nicht freizugeben (Windows XP gibt den Speicher beim Beenden der Anwendung frei, oder?), oder eben den von Dir vorgeschlagenen Workaround zu verwenden. Was hinterlässt potentiel mehr "Reste"? Vielleicht findet auch noch jemand den genauen Grund. Ich werde mit meinen bescheidenen Mitteln auch noch mal forschen. Gruß und noch mal vielen Dank, StTüff |
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:20 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