AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi Dispose = Exception, kein Dispose = Memory Leak
Thema durchsuchen
Ansicht
Themen-Optionen

Dispose = Exception, kein Dispose = Memory Leak

Ein Thema von jensw_2000 · begonnen am 20. Sep 2007 · letzter Beitrag vom 20. Sep 2007
Antwort Antwort
jensw_2000
(Gast)

n/a Beiträge
 
#1

Dispose = Exception, kein Dispose = Memory Leak

  Alt 20. Sep 2007, 11:05
Die Themen Callback und Pointer auf Records wurden hier ja schön öfter diskutiert.
Ich habe das Prinzip aber offensichtlich immer noch nicht ganz verstanden.

Folgendes Problem:

Ich fordere in der aufrufenden Prozedur mit new(PointerAufRecord) Speicher an und übergebe diesen Pointer an die empfangende Routine.
Dort muss ich den Speicher doch mit Dispose (PointerAufRecord) wieder freigeben, dachte ich ...

Dieses Prinzip verwende ich zum Datenaustausch zwischen einer Clientapplikation und einer DLL, die als API für Drittanbieter dienen soll.

Irgendwie klappt es mit dem Dispose nicht so, wie ich es gerne hätte.

Wenn ich aus der Client-Applikation eine DLL Funktion (z.B. Register_ClientApplication(aRecordTRecord) ) aufrufe, und dort den Speicher von TRecord mit Dispose freigebe, dann gibt es eine Exception beim Beenden des Programmes.

Wenn ich nach diesem Prinzip Daten in die Gegenrichtung (DLL > Clientanwendung) via Callback Funktion transportiere und den Speicher in der Client-Anwendung mit Dispose freigenen möchte, dann gibt es eine Exception beim Aufruf von Dispose.

Lasse ich das Dispose in der DLL und in der Anwendung weg, dann "läuft alles super". Wäre da nicht das "kleine" Problem, dass der Speicher nicht freigegeben wird ....

Ich habe ein kleines Spielprojekt angehängt.
Werft ihr bitte mal einen Blick drauf ?


Aufruf
Delphi-Quellcode:
procedure Register_API( const Servername:String );
begin
  ApiRegisterInfoRec := new(PTApiRegisterInfoRec);
  // Record füllen
  ApiRegisterInfoRec.Servername    := Servername;
  // Callback Prozeduren übergeben
  ApiRegisterInfoRec.OnState    := @OnGetApiState;
  ApiRegisterInfoRec.OnError := @OnGetApiError;
  
  // DLL Register_ClientApplication aufrufen
  Register_ClientApplication(ApiRegisterInfoRec);
  // DLL räumt den Speichern von ApiInitRec
end;
DLL Funktion
Delphi-Quellcode:
function Register_ClientApplication ( aApiRegisterInfo : PTApiRegisterInfoRec):bool; stdcall;
begin
  try
    // Callback Funktionen initialisieren
    @Callback_OnState          := @aApiRegisterInfo.OnState;
    @Callback_OnError          := @aApiRegisterInfo.OnError;

    // Infos aus ApiRegisterInfo übernehmen
    PipeServername                := aApiRegisterInfo.Servername;

    // Speicher von aApiRegisterInfo räumen
    // Dispose geht nicht. Exception beim Beenden der Client-Applikation
    // Dispose(aApiRegisterInfo);

    Registered := true;
  except
    on e:exception do
    begin
      registered := false;
      if assigned(Callback_OnError) then
        OnSendError(1001,esClientAPI,e.Message);
      raise exception.create('Fatal: Register_ClientApplication'+#13#10+e.Message);
    end;
  end;
  result := registered;

  // mit aktuellem Status antworten
  OnSendState(registered, true,101, PipeServername);
end;
Angehängte Dateien
Dateityp: zip spielprojekt_dll__callback_und_records_149.zip (923,8 KB, 0x aufgerufen)
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#2

Re: Dispose = Exception, kein Dispose = Memory Leak

  Alt 20. Sep 2007, 11:09
Achtung! du hast zwei speichermanager und kannst nicht einfach Speicher in dem einen Programm anfordern und in dem anderen freigeben.
Warum nimmst du das Dispose nicht auch in die aufrufende Exe?

Edit:
Es sollte auch so gehen (ganz ohne dispose und new)..
Aufruf:
Delphi-Quellcode:
procedure Register_API( const Servername:String );
var ApiRegisterInfoRec:TApiRegisterInfoRec;
begin
  // Record füllen
  ApiRegisterInfoRec.Servername := Servername;
  // Callback Prozeduren übergeben
  ApiRegisterInfoRec.OnState := @OnGetApiState;
  ApiRegisterInfoRec.OnError := @OnGetApiError;
  
  // DLL Register_ClientApplication aufrufen
  Register_ClientApplication(@ApiRegisterInfoRec);
end;
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Stefan.Buchholtz

Registriert seit: 2. Dez 2004
Ort: Mönchengladbach
7 Beiträge
 
Delphi 7 Enterprise
 
#3

Re: Dispose = Exception, kein Dispose = Memory Leak

  Alt 20. Sep 2007, 11:16
Wenn dynamisch belegter Speicher zwischen verschiedenen Modulen ausgetauscht wird, muss immer das Modul den Speicher freigeben, das ihn auch belegt hat. Alternativ kannst du sowohl im Programm als auch in der DLL als erstes die Unit ShareMem einbinden - das ersetzt den Standard-Speichermanager der Delphi-Runtime durch einen, der auch über Modulgrenzen funktioniert. Dann muss zusammen mit dem Programm allerdings noch die borlndmm.dll installiert werden, die diesen Speichermanager enthält.

Ohne ShareMem ist es so richtig:

Delphi-Quellcode:
procedure Register_API( const Servername:String );
begin
  ApiRegisterInfoRec := new(PTApiRegisterInfoRec);
  // Record füllen
  ApiRegisterInfoRec.Servername := Servername;
  // Callback Prozeduren übergeben
  ApiRegisterInfoRec.OnState := @OnGetApiState;
  ApiRegisterInfoRec.OnError := @OnGetApiError;
  
  // DLL Register_ClientApplication aufrufen
  Register_ClientApplication(ApiRegisterInfoRec);

  // Speicher von ApiInitRec aufräumen
  Dispose(ApiRegisterInfoRec);
end;
Stefan
Stefan Buchholtz
  Mit Zitat antworten Zitat
jensw_2000
(Gast)

n/a Beiträge
 
#4

Re: Dispose = Exception, kein Dispose = Memory Leak

  Alt 20. Sep 2007, 12:11
Ich habe jetzt das new() und Dispose() weggelassen und als Parameter "aRecord:TeinRecord" anstatt "aRecordTeinRecord" übergeben.

Sieht so aus als hätte ich mir das Leben zu schwehr gemacht. Es funktioniert soweit.

Sharemem will ich bewusst nicht benutzen, weil die API kompatibel mit C++ sein muss.

Danke.
  Mit Zitat antworten Zitat
Dezipaitor

Registriert seit: 14. Apr 2003
Ort: Stuttgart
1.701 Beiträge
 
Delphi 7 Professional
 
#5

Re: Dispose = Exception, kein Dispose = Memory Leak

  Alt 20. Sep 2007, 13:35
Du kannst auch LocalAlloc und LocalFree verwenden. Ich habs zwar nie wirklich direkt ausprobiert.
Aber es gibt WinApi funktionen, die rufen LocalFree oder LocalAlloc von dem Speicher auf, den ich selbst durch LocalAlloc oder LocalFree erstellt oder zerstört habe.
Die WinAPI ist ja selbst in DLLs.
Christian
Windows, Tokens, Access Control List, Dateisicherheit, Desktop, Vista Elevation?
Goto: JEDI API LIB & Windows Security Code Library (JWSCL)
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#6

Re: Dispose = Exception, kein Dispose = Memory Leak

  Alt 20. Sep 2007, 13:58
Zitat von Dezipaitor:
Du kannst auch LocalAlloc und LocalFree verwenden. Ich habs zwar nie wirklich direkt ausprobiert.
Aber es gibt WinApi funktionen, die rufen LocalFree oder LocalAlloc von dem Speicher auf, den ich selbst durch LocalAlloc oder LocalFree erstellt oder zerstört habe.
Die WinAPI ist ja selbst in DLLs.
Das geht (oder virtualalloc...) auch. Nur sollte man sich eben überlegen, ob das wirklich nötig ist. Der Speichermanager ist ja nicht dafür da um uns das Leben schwer zu machen, sondern um das Programm zu beschleunigen. Der hängt nämlich genau zwischen new/dispose/realloc/etc. und der WinAPI (virtualalloc und virtuallfree).
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Dezipaitor

Registriert seit: 14. Apr 2003
Ort: Stuttgart
1.701 Beiträge
 
Delphi 7 Professional
 
#7

Re: Dispose = Exception, kein Dispose = Memory Leak

  Alt 20. Sep 2007, 14:05
Also der beste Zweck ist bei Callback Funktionen (z.b. auch bei COM).
Wenn eine Funktion als Callback aufgerufen wird und ein Speicher erstellen soll, dann sollte er von der aufzurufende Fkt gelöscht werden.
Christian
Windows, Tokens, Access Control List, Dateisicherheit, Desktop, Vista Elevation?
Goto: JEDI API LIB & Windows Security Code Library (JWSCL)
  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 08:30 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