Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi [Erledigt] Preview Handler in VCL erzeugt MemoryLeak (https://www.delphipraxis.net/179132-%5Berledigt%5D-preview-handler-vcl-erzeugt-memoryleak.html)

Aviator 16. Feb 2014 15:31


[Erledigt] Preview Handler in VCL erzeugt MemoryLeak
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo DPler.
Da ich mit meinem Programm sehr viele Dokumente abspeichere und danach natürlich auch wieder anzeigen lassen möchte, habe ich mir überlegt, einen Preview Handler in meinem Projekt mit einzubinden. Ich möchte also Word, Excel, PDF, ... Dateien in meinem Programm per Vorschau anzeigen.

Den Quellcode, wie das denn funktionieren sollte, habe ich von hier. Diese Unit funktioniert auch und macht auch das was es soll.

Ich habe mir zum Testen das Beispielprojekt von dieser Seite heruntergeladen und ausprobiert. Da ich bei meinem neuesten Projekt aber peinlichst darauf achte, dass ich keine Memory Leaks erzeuge, habe ich auch hier nachgeschaut, ob alles sauber wieder freigegeben wird und keine Leaks entstehen.

Also habe ich die Zeile
Delphi-Quellcode:
ReportMemoryLeaksOnShutdown := True;
in das Beispiel Projekt eingebunden, eine Vorschau geladen und das Programm wieder geschlossen. Ich dachte schon "na super - alles funktioniert wie es soll also kann ich es bedenkenlos benutzen". 10 Sekunden nach der Beendigung des Programms kam dann allerdings die Meldung, dass doch ein MemoryLeak erkannt wurde und das Programm sogar nicht mehr funktionieren würde. (Im TaskManager wird der Prozess auch nach der Beendigung des Programmes angezeigt. Auch wenn ich die Zeile
Delphi-Quellcode:
ReportMemoryLeaksOnShutdown := True;
weglasse.)

In der Meldung steht, dass eine Instanz des
Delphi-Quellcode:
TStreamAdapter
nicht freigegeben wurde.

Nun meine Frage: Wie bekomme ich diesen "Fehler" weg bzw. wie lässt sich das umgehen? Ich bin für jede Hilfe dankbar die ich hier bekomme.

Im Anhang noch die Fehlermeldung.

Sir Rufo 16. Feb 2014 15:45

AW: Preview Handler in VCL erzeugt MemoryLeak - Lösung gesucht
 
In Zeile 42 ist der Fehler

himitsu 16. Feb 2014 15:51

AW: Preview Handler in VCL erzeugt MemoryLeak - Lösung gesucht
 
Zitat:

Zitat von Sir Rufo (Beitrag 1248097)
In Zeile 42 ist der Fehler

Pro 7? :lol:

Sir Rufo 16. Feb 2014 15:54

AW: Preview Handler in VCL erzeugt MemoryLeak - Lösung gesucht
 
Zitat:

Zitat von himitsu (Beitrag 1248101)
Zitat:

Zitat von Sir Rufo (Beitrag 1248097)
In Zeile 42 ist der Fehler

Pro 7? :lol:

Passt gut gerade ;)

jaenicke 16. Feb 2014 16:24

AW: Preview Handler in VCL erzeugt MemoryLeak - Lösung gesucht
 
Er hat den Quelltext doch verlinkt... :roll:

Das passiert auch mit der Demo schon. Aber ist wohl zu viel verlangt das auszuprobieren. :roll:

In dem Quelltext sind leider zwei gravierende Fehler drin. Der wichtigste ist, dass der TFileStream freigegeben wird, obwohl der TStreamAdapter mit soOwned erzeugt wird. Dadurch gibt es einen Fehler beim Freigeben (logisch) und daher rührt das Speicherleck.

Der zweite wichtige Fehler ist, dass dort der Registry-Schlüssel mit
Delphi-Quellcode:
LRegistry.OpenKey(LKey, True);
frecherweise einfach erzeugt wird, statt ihn nur zu versuchen zu öffnen und den Rückgabewert auszuwerten.
Richtig daher:
Delphi-Quellcode:
    if LRegistry.OpenKey(LKey, False) then
    begin
      Result := LRegistry.ReadString('');
      LRegistry.CloseKey;
    end
    else
      Result := '';

Aviator 16. Feb 2014 16:27

AW: Preview Handler in VCL erzeugt MemoryLeak - Lösung gesucht
 
Danke Jaenicke, ich versuche mal das Problem mit deinen genannten Hinweisen zu lösen.

@Sir Rufo: Bitte den Beitrag das nächste Mal ganz durchlesen und dann antworten. Danke.

Aviator 16. Feb 2014 16:35

AW: Preview Handler in VCL erzeugt MemoryLeak - Lösung gesucht
 
@Jeanicke: Habe das Problem denke ich mit deinen Stichpunkten lösen können, indem ich 1. deinen Teil mit dem Registry Code ersetzt habe und 2. im OnDestroy die Zeilen
Delphi-Quellcode:
if FFileStream<>nil then
  FFileStream.Free;
entfernt habe. Ob das allerdings so richtig ist, weiß ich nicht. Wäre nett, wenn du mir sagen könntest ob das so stimmt. Der Memory Leak kommt zumindest nicht mehr.

Ein kleines weiteres Problem (was allerdings nicht so super tragisch ist aber ich gerne gelöst hätte) ist, dass das Programm beim Beenden noch ca. 10 Sekunden lang offen bleibt. Kennt jemand den Grund dafür und wie man das möglicherweise beheben kann, oder ist es einfach so (was ich mit nicht vorstellen kann) ?

Zitat:

Das passiert auch mit der Demo schon. Aber ist wohl zu viel verlangt das auszuprobieren.
Wenn du damit mich meintest: Oben schrieb ich bereits, dass ich das Beispielprojekt geladen und getestet habe und ich auch deshalb auf den Fehler aufmerksam geworden bin. ;)

jaenicke 16. Feb 2014 17:50

AW: Preview Handler in VCL erzeugt MemoryLeak - Lösung gesucht
 
Zitat:

Zitat von Aviator (Beitrag 1248107)
Zitat:

Das passiert auch mit der Demo schon. Aber ist wohl zu viel verlangt das auszuprobieren.
Wenn du damit mich meintest: Oben schrieb ich bereits, dass ich das Beispielprojekt geladen und getestet habe und ich auch deshalb auf den Fehler aufmerksam geworden bin. ;)

Nein, ich meinte Sir Rufo, da ich davon ausgegangen bin, dass er den Link gesehen hatte, aber trotzdem nicht erst einmal dort nachgeschaut und ausprobiert hat. Das kommt hier in der DP in letzter Zeit leider häufiger vor, dass ähnliche Kurzbeiträge druntergehauen werden obwohl im Beitrag eigentlich alles drin ist, es nachzuvollziehen aber vielleicht 1-2 Minuten mehr erfordert hätte.
(Hauptsache Beitragszähler erhöhen?)

Zitat:

Zitat von Aviator (Beitrag 1248107)
@Jeanicke: Habe das Problem denke ich mit deinen Stichpunkten lösen können, indem ich 1. deinen Teil mit dem Registry Code ersetzt habe und 2. im OnDestroy die Zeilen

Im LoadPreviewHandler muss die Freigabe des Streams auch noch raus.

Bei mir passiert das mit der Wartezeit nicht mehr, das hatte ich anfangs aber auch. Ich glaube das liegt am eingebetten Programm. Das müsste man vielleicht noch genauer untersuchen. Da das ganze über COM läuft, vermute ich aber, dass da noch auf etwas gewartet wird.

Aviator 16. Feb 2014 18:12

AW: Preview Handler in VCL erzeugt MemoryLeak - Lösung gesucht
 
Hi und danke für die Antwort. Die Dauer des Beendens ist zwar dennoch vorhanden, aber es kommen keine Fehler (Memory Leaks) mehr. Leider kenne ich mich mit COM nicht aus und kann daher auch nicht nachvollziehen, wieso es so lange dauert bis das Programm beendet ist. Aber dennoch danke für einen möglichen Hinweis an was es liegen könnte. Beim Debuggen wird auf jeden Fall im OnDestroy beider Klassen sehr lange gewartet. Leider kann ich nirgends irgendwie tiefer irgendwo debuggen um den Fehler zu finden.
Aber dieses Problem will ich mal etwas nach hinten schieben, es sei denn es kennt jemand eine Lösung bzw. einen Anhaltspunkt an was es liegen könnte.

jaenicke 16. Feb 2014 18:30

AW: Preview Handler in VCL erzeugt MemoryLeak - Lösung gesucht
 
Liste der Anhänge anzeigen (Anzahl: 1)
Was ich noch vergessen habe:
Statt OpenKey sollte in GetPreviewHandlerCLSID noch OpenKeyReadOnly rein, damit es auch ohne Adminrechte funktioniert.

Wenn es beim Beenden hängt, hängt es bei mir in der Preview-DLL beim Unload wie man im Stacktrace ja sieht:
Anhang 40733
Insofern wird sich da wohl nicht viel machen lassen.

Aviator 16. Feb 2014 18:34

AW: Preview Handler in VCL erzeugt MemoryLeak - Lösung gesucht
 
Super. Danke das du nach einer Lösung gesucht hast.

Die Zeile habe ich von mir aus schon mit OpenKeyReadOnly ersetzt. Trotzdem danke für den Hinweis.

Furtbichler 17. Feb 2014 00:27

AW: Preview Handler in VCL erzeugt MemoryLeak - Lösung gesucht
 
Zitat:

Zitat von jaenicke (Beitrag 1248119)
Nein, ich meinte Sir Rufo, da ich davon ausgegangen bin, dass er den Link gesehen hatte, aber trotzdem nicht erst einmal dort nachgeschaut und ausprobiert hat. Das kommt hier in der DP in letzter Zeit leider häufiger vor, dass ähnliche Kurzbeiträge druntergehauen werden obwohl im Beitrag eigentlich alles drin ist, es nachzuvollziehen aber vielleicht 1-2 Minuten mehr erfordert hätte.
(Hauptsache Beitragszähler erhöhen?)

Na, wenigstens haben wir hier ein echtes Soziophob, aka 'sas Jänicke', das wohl sonst nichts zu tun hat, und die 1-2 Minuten verschwendet, um einem lieblos dahingerotzen Link zu folgen, sich die Quellen runterzuladen, die Fehler zu finden und zu posten und das in gerade 1-2 Minuten.

Respekt Wastl. 1-2 Minuten könnten dezent untertrieben sein. Außer, Du hast den Fluxkompensator und Dimensionsfalten.

Frage: Wieso musst Du auf anderen herumtrampeln, um dich selbst zu erhöhen? Was fehlt Dir? Ach, ich weiß: Fängt mit 'S' an und hört mit 'wuststein' auf. Dazwischen ist noch ein 'elbstbe' Und: Ja, es ist nicht das erste mal, daß Du so unangenehm auffällst..

jaenicke 17. Feb 2014 05:45

AW: Preview Handler in VCL erzeugt MemoryLeak - Lösung gesucht
 
Zitat:

Zitat von Furtbichler (Beitrag 1248141)
1-2 Minuten könnten dezent untertrieben sein. Außer, Du hast den Fluxkompensator und Dimensionsfalten.

In ca. 1 Minute hatte ich gesehen, dass die Demo auch dieses Problem hat. Da ist ja auch nix weiter dabei.

Bis ich den Fehler an sich gesehen hatte waren es noch einmal 5-10 Minuten, aber davon hatte ich ja auch nicht gesprochen.

mkinzler 17. Feb 2014 06:35

AW: [Erledigt] Preview Handler in VCL erzeugt MemoryLeak
 
Zitat:

Frage: Wieso musst Du auf anderen herumtrampeln, um dich selbst zu erhöhen? Was fehlt Dir? Ach, ich weiß: Fängt mit 'S' an und hört mit 'wuststein' auf. Dazwischen ist noch ein 'elbstbe' Und: Ja, es ist nicht das erste mal, daß Du so unangenehm auffällst..
Diese Frage solltest Du Dir auch mal stellen.

Daniel 17. Feb 2014 07:32

AW: Preview Handler in VCL erzeugt MemoryLeak - Lösung gesucht
 
Zitat:

Zitat von Furtbichler (Beitrag 1248141)
Frage: Wieso musst Du auf anderen herumtrampeln, um dich selbst zu erhöhen? Was fehlt Dir? Ach, ich weiß: Fängt mit 'S' an und hört mit 'wuststein' auf. Dazwischen ist noch ein 'elbstbe' Und: Ja, es ist nicht das erste mal, daß Du so unangenehm auffällst..

Da hatte wohl jemand einen sehr schlechten Abend. :roll:
Und es ist auch keineswegs das erste mal, dass Du mit solchen Beiträgen auffällst.

Ich wiederhole Triviales: Es steht jedem frei, auf ein Thema auch mal nicht zu antworten - insbesondere dann, wenn man nichts Konstruktives beizutragen hat.

fs999 10. Mär 2014 15:17

AW: [Erledigt] Preview Handler in VCL erzeugt MemoryLeak
 
Die Variabel LIStream wird nicht genilt...

Nach
Delphi-Quellcode:
LInitializeWithStream.Initialize(LIStream, STGM_READ);
,
einfach
Delphi-Quellcode:
LIStream := nil;
dahinter.

Ich habe aber noch ein Problem, mit BDS 2006 funktioniert es überhaupt nicht, nach eine Minute warten : EOleSystemError : Unspecified Error.
Und noch schlimmer wenn ich das Programm ohne Delphi starte, bekomme ich nach 5 Sekunden die Windowsmeldung dass das Programm abgestürzt ist...

Habe die fehlende Units PropSys and StructuredQueryCondition in das Appliverzeichnis kopiert und IPreviewInterface mit ein paar Konstanten eingefügt.

Der Fehler ist auf diese Line in LoadPreviewHandler :
Delphi-Quellcode:
FPreviewHandler := CreateComObject(LPreviewGUID) as IPreviewHandler;

jaenicke 10. Mär 2014 15:45

AW: [Erledigt] Preview Handler in VCL erzeugt MemoryLeak
 
Zitat:

Zitat von fs999 (Beitrag 1251399)
Die Variabel LIStream wird nicht genilt...

Wozu auch?
Der Referenzzähler wird dann eben erst am Ende der Methode dekrementiert, aber das stört doch auch nicht, oder?

Zitat:

Zitat von fs999 (Beitrag 1251399)
Ich habe aber noch ein Problem, mit BDS 2006 funktioniert es überhaupt nicht, nach eine Minute warten : EOleSystemError : Unspecified Error.

Bei welchem Betriebssystem denn?
Und funktioniert die beiliegende kompilierte Demo vielleicht auch nicht?

fs999 11. Mär 2014 13:04

AW: [Erledigt] Preview Handler in VCL erzeugt MemoryLeak
 
Zitat:

Zitat von jaenicke (Beitrag 1251404)
Der Referenzzähler wird dann eben erst am Ende der Methode dekrementiert, aber das stört doch auch nicht, oder?

Das hat aber gebracht dass das Programm nicht abstürtzt.

Zitat:

Zitat von jaenicke (Beitrag 1251404)
Bei welchem Betriebssystem denn?
Und funktioniert die beiliegende kompilierte Demo vielleicht auch nicht?

-Win7 64bit.
-Die kompilierte Demo benutzt LInitializeWithFile, ich benutze LInitializeWithStream.

Mea culpa, dass hätte ich sagen müssen, ich habe die Streamroutine als erste geswapt...

Delphi-Quellcode:
  if FPreviewHandler.QueryInterface(IInitializeWithStream, LInitializeWithStream) = S_OK then
  begin
      FFileStream := TFileStream.Create(FFileName, fmOpenRead or fmShareDenyNone);
      LIStream := TStreamAdapter.Create(FFileStream, soOwned) as IStream;
      LInitializeWithStream.Initialize(LIStream, STGM_READ);
      LIStream := nil;
  end
  else
  if FPreviewHandler.QueryInterface(IInitializeWithFile, LInitializeWithFile) = S_OK then
    LInitializeWithFile.Initialize(StringToOleStr(FFileName), STGM_READ)
  else

himitsu 11. Mär 2014 13:12

AW: [Erledigt] Preview Handler in VCL erzeugt MemoryLeak
 
Vor dem Aufruf von QueryInterface sollte die Interface-Variable unbedingt leer sein. Wenn nicht, dann vorher manuell auf NIL setzen.
Vorallem innerhalb von Schleifen, oder wenn die Variable vorher für was Anderes verwendet wurde.

QueryInterface, bzw. GetInterface sind mit Out-Parametern deklariert, womit die Eingabe "verworfen" wird, unter Ausschluß der Referenzzählung.
Sowas kann auch bei anderen Funktionen vorkommen, also immer schön aufpassen.

Zitat:

Delphi-Quellcode:
function TInterfacedObject.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
  if GetInterface(IID, Obj) then
    Result := 0
  else
    Result := E_NOINTERFACE;
end;

function TObject.GetInterface(const IID: TGUID; out Obj): Boolean;
begin
  Pointer(Obj) := nil; // <<<<<
  ...
end;


fs999 11. Mär 2014 15:42

AW: [Erledigt] Preview Handler in VCL erzeugt MemoryLeak
 
Der Fehler tritt auf der vorige Linie auf :
Delphi-Quellcode:
FPreviewHandler := CreateComObject(LPreviewGUID) as IPreviewHandler;

idefix2 31. Mai 2015 10:11

AW: [Erledigt] Preview Handler in VCL erzeugt MemoryLeak
 
Ich hätte gerne den Windows preview Handler, von dem in diesem Thread die Rede ist, in mein Programm eingebunden - unter Delphi 2009 ist aber das Interface IPreviewHandler anscheinend noch nicht definiert (oder muss man da noch etwas extra in die uses-clause aufnehmen?), deshalb kompiliert die Unit nicht.
Gibt es eine Möglichkeit, das auch unter Delphi 2009 zum Laufen zu bringen?

Aviator 31. Mai 2015 11:56

AW: [Erledigt] Preview Handler in VCL erzeugt MemoryLeak
 
Die Interfaces sind bei XE3 in der WinAPI.PropSys Unit deklariert. Folglich sollten diese unter Delphi 2009 in der Unit PropSys deklariert sein. Allerdings weiß ich nicht, ob diese dort schon existiert haben oder ob diese nicht in einer anderen Unit deklariert wurden. Habe leider kein Delphi 2009 sondern nur XE3 und XE4.

Edit: Sorry das Interface IPreviewHandler ist in der Unit ShlObj definiert. Ich meinte die anderen Interfaces IInitializeWithFile, ...

idefix2 31. Mai 2015 16:20

AW: [Erledigt] Preview Handler in VCL erzeugt MemoryLeak
 
Tja, unter Delphi 2009 gibt es diese Interfaces offenbar noch nicht, die Unit ist ja eingebunden.

himitsu 31. Mai 2015 16:37

AW: [Erledigt] Preview Handler in VCL erzeugt MemoryLeak
 
MSDN-Library durchsuchenIPreviewHandler
Im MSDN/PSDK steht ja genau drin, wie das Interface aussieht und man kann es problemlos auch selber implementieren.

Und es ist nicht so, als wenn man nicht auch sowas in Fremdkomponenten finden könnte.
Bei Google suchenIPreviewHandler Delphi

idefix2 31. Mai 2015 17:56

AW: [Erledigt] Preview Handler in VCL erzeugt MemoryLeak
 
Nachdem ich mich bis jetzt recht wenig mit COM Klassen beschäftigt habe, bin ich auf der Suche nach einer zumindest halbfertigen Lösung (Delphi Wrapper). Natürlich kann man mit umfangreichen Studium der Dokuentation prinzipiell alles programmieren, aber hier wäre mir eine fertige Komponente oder Klasse entschieden lieber.

Dazu Google zu verlinken, ist nicht allzu hilfreich - dort habe ich schon gesucht. Man findet sehr viel, aber ich habe nichts brauchbares entdeckt, vor allem, wie es aussieht, nicht für Delphi 2009.

himitsu 31. Mai 2015 18:07

AW: [Erledigt] Preview Handler in VCL erzeugt MemoryLeak
 
Am Einfachsten ist es mal in JEDI und Co. zu schauen, denn das ist ja grade eine Sammlung vieler Headerübersetzungen.

Aviator 31. Mai 2015 18:24

AW: [Erledigt] Preview Handler in VCL erzeugt MemoryLeak
 
Also wenn es nur um die Deklaration des Interfaces geht, dann kann ich dir mit der aus meinem XE3 dienen.

Delphi-Quellcode:
  IPreviewHandler = interface(IUnknown)
    [SID_IPreviewHandler]
    function SetWindow(hwnd: HWND; var prc: TRect): HRESULT; stdcall;
    function SetRect(var prc: TRect): HRESULT; stdcall;
    function DoPreview: HRESULT; stdcall;
    function Unload: HRESULT; stdcall;
    function SetFocus: HRESULT; stdcall;
    function QueryFocus(var phwnd: HWND): HRESULT; stdcall;
    function TranslateAccelerator(var pmsg: TMsg): HRESULT; stdcall;
  end;
Ob du noch mehr brauchst, weiß ich allerdings nicht.

idefix2 31. Mai 2015 20:22

AW: [Erledigt] Preview Handler in VCL erzeugt MemoryLeak
 
Danke, damit werde ich es einmal versuchen. Leider habe ich wieder eine andere dringende Baustelle, sodass ich nicht gleich dazukomme.
Die ganze Unit schaut mir nicht allzu kompliziert aus, mit den richtigen Interfacedeklarationen sollte nicht mehr allzuviel fehlen, dass es auch unter Delphi 2009 läuft. In dem Bereich sollte sich bei der Sprache seither nicht gar so viel verändert haben. :-D


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:54 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