Delphi-PRAXiS
Seite 3 von 3     123   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Problem beim Beenden (DLL mit Formular und mODBC) (https://www.delphipraxis.net/99441-problem-beim-beenden-dll-mit-formular-und-modbc.html)

StTüff 2. Okt 2007 10:01

Re: Problem beim Beenden (DLL mit Formular und mODBC)
 
Hallo!

Ich habe jetzt noch folgendes herausgefunden:
Wenn ich das Formular so
Delphi-Quellcode:
Form1:=TForm1.Create(Application);
oder so
Delphi-Quellcode:
Application.CreateForm(TForm1, Form1);
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.
=> 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

Flocke 2. Okt 2007 11:00

Re: Problem beim Beenden (DLL mit Formular und mODBC)
 
<offtopic>

Zitat:

Zitat von peschai
Hallo
und bitte als guten stil verwende ich persönlich immer FreeAndNil und das als paar mit der abfrage auf Assigned.
Delphi-Quellcode:
if Assignd(Form1) then
  begin
    FreeAndNil(Form1)
  end;

Ähem! Nur FreeAndNil reicht: das prüft nämlich schon auf nil bzw. Assigned.
Weniger Zeilen machen dein Programm lesbarer!

</offtopic>

peschai 2. Okt 2007 11:10

Re: Problem beim Beenden (DLL mit Formular und mODBC)
 
Zitat:

Ähem! Nur FreeAndNil reicht: das prüft nämlich schon auf nil bzw. Assigned.
Weniger Zeilen machen dein Programm lesbarer!
Pustekuchen!
Dann schau dir mal den Source an (Delphi2007Prof) von SysUtils.pas:

Delphi-Quellcode:
procedure FreeAndNil(var Obj);
var
  Temp: TObject;
begin
  Temp := TObject(Obj);
  Pointer(Obj) := nil;
  Temp.Free;
end;
Da ist keine Abfrage nach assigend! :angel:

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;

Flocke 2. Okt 2007 11:24

Re: Problem beim Beenden (DLL mit Formular und mODBC)
 
Zitat:

Zitat von peschai
Da ist keine Abfrage nach assigend! :angel:

Stimmt ... die ist in der Methode TObject.Free :P

StTüff 2. Okt 2007 11:42

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

peschai 2. Okt 2007 12:42

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:
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;
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.

StTüff 2. Okt 2007 14:23

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

Flocke 2. Okt 2007 15:01

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:
procedure TmSession.FreeHENV;
begin
  if FHENV = 0 then
    exit;
  try
    SQLFreeHandle(SQL_HANDLE_ENV, FHENV);
  except
  end;
  FHENV:=0;
end;
@peschai:
Zitat:

Zitat von peschai
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.

Man arbeitet in Delphi immer mit von TObject abgeleiteten Klassen. Hier gibt es für die Freigabe von Objekten zwei relevante Funktionen, die du ja schon genannt hast:

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.

StTüff 4. Okt 2007 09:31

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.
Seite 3 von 3     123   

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