AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Handle Leak finden

Ein Thema von Assertor · begonnen am 13. Jan 2009 · letzter Beitrag vom 19. Jan 2009
Antwort Antwort
Assertor

Registriert seit: 4. Feb 2006
Ort: Hamburg
1.296 Beiträge
 
Turbo C++
 
#1

Handle Leak finden

  Alt 13. Jan 2009, 13:14
Hi,

in Ergänzung zu einem Thread aus dem letzten Jahr bzgl. THtmlViewer (hier) wollte ich mal fragen, ob jemand eine effiziente Methode kennt, Handle Leaks von Delphi Anwendungen zu finden.

Dem Handle-Verbrauch kann ich im Windows Task-Manager bildlich folgen: Von 202 Handles wächst das nach ~ 500 Druckaufträgen auf ~ 500 Handles...

Ich habe es schon mit AppVerifier und AQtime versucht, aber bekomme keine klare Aussage bzw. Code-Zeile heraus. Da ich eine Software für den "Dauerbetrieb" fertigstellen muß, brauche ich hier wohl etwas hilfe...

Kennt jemand hier einen guten Weg?

Gibt es sowas wie die üblichen Verdächtigen für Memory Leaks (FastMM, madExcept) auch für (Resource) Handles?

Gruß Assertor
Frederik
  Mit Zitat antworten Zitat
nahpets
(Gast)

n/a Beiträge
 
#2

Re: Handle Leak finden

  Alt 16. Jan 2009, 10:15
Hallo Assertor,

eine Lösung hab' ich nicht, nicht mal 'nen Ansatz. Nur das Problem, dass ein Programm von mir immer mehr Handles offen hat und die Threadanzahl kontinuierlich steigt.

Ein paar "unschärfen" habe ich inzwischen gefunden, welche ist egal, das wie könnte Dich interessieren:

Von Sysinternals gibt es den Process Explorer (www.sysinternals.com - das gehört inzwischen Microsoft und Du wirst auch im Technet fündig).

Der Process Explorer ist ein Ersatz des Taskmanagers und kann Dir (einen Teil) der vom Programm genutzen Handle anzeigen.
Du wählst in der Prozessliste Dein Programm aus und kannst dann über Ctrl+H die Handle anzeigen lassen.

Auf die Art und Weise bin ich zumindest dahintergekommen, dass ich beim Lesen der Eventlogs der Server ein Problem habe. Da bleiben sporadisch Handles offen und damit die Threads, die sie genutzt haben, bestehen.

Momentan versuche ich mit dem Process Monitor von der gleichen Seite ein paar zusätzliche Informationen zu erlangen, weiß aber noch nicht, ob das Werkzeug hilfreich ist, die Informationsmenge ist mir (momentan) noch zu hoch.
Was mir bisher auffällt ist nur, des regelmäßig ein RegOpenKey auf HKCU\Software\Classes\CLSID\... erfolgt, das Ergebnis NAME NOT FOUND ist und der Process Explorer genau hierfür eine Menge von Handles anzeigt, die allem Anschein nach nicht geschlossen werden. Mir ist in meinem Programm nur keine Stelle bekannt, an der ich auf diesen Schlüssel zugreife und ein entsprechendes RegCloseKey vergessen haben könnte.

Naja, egal, meine Probleme brauchen Dich nicht zu interessieren, aber eventuell hilft Dir ja der Weg der Fehlersuche ein bisserl weiter.
  Mit Zitat antworten Zitat
Assertor

Registriert seit: 4. Feb 2006
Ort: Hamburg
1.296 Beiträge
 
Turbo C++
 
#3

Re: Handle Leak finden

  Alt 16. Jan 2009, 10:53
Hallo Stephan,

Zitat von nahpets:
Von Sysinternals gibt es den Process Explorer (www.sysinternals.com - das gehört inzwischen Microsoft und Du wirst auch im Technet fündig).
Danke für den Hinweis, auch wenn ich das Tool schon ein paar Jährchen kenne

Zitat von nahpets:
Was mir bisher auffällt ist nur, des regelmäßig ein RegOpenKey auf HKCU\Software\Classes\CLSID\... erfolgt, das Ergebnis NAME NOT FOUND ist und der Process Explorer genau hierfür eine Menge von Handles anzeigt, die allem Anschein nach nicht geschlossen werden. Mir ist in meinem Programm nur keine Stelle bekannt, an der ich auf diesen Schlüssel zugreife und ein entsprechendes RegCloseKey vergessen haben könnte.
Im Gegenzug kann ich Dir aus meinen Erfahrungen mit AQtime etwas helfen - die Meldungen der Registry habe ich dort auch gesehen. Die "NAME NOT FOUND" Geschichte geht teilweise auf die RTL, teilweise auf Komponenten wie z.B. Indy zurück. Im Prinzip wird nur das Vorhandensein von Werten geprüft, kommt die o.g. Meldung gibt es diesen nicht. Also kein Grund sich deswegen zu sorgen.

Das Problem ist die Identifikation der Art und Quelle der offenen Handles. Im AQtime geht dies differenziert z.B. nach GDI/User Handles oder auch File & Registry Zugriffen.

Ein ebenso gutes Tool ist der Process Monitor (auch von SysInternals) - dort ist es teilweise einfacher als im Process Explorer nach Zugriffen zu suchen, da Du hier Filter vorgeben kannst.

Gruß Assertor
Frederik
  Mit Zitat antworten Zitat
Benutzerbild von uligerhardt
uligerhardt

Registriert seit: 19. Aug 2004
Ort: Hof/Saale
1.735 Beiträge
 
Delphi 2007 Professional
 
#4

Re: Handle Leak finden

  Alt 16. Jan 2009, 12:00
MemProof konnte das WIMRE. Ich hab aber keine Ahnung, ob das Ding mit D2009 funktioniert.
Uli Gerhardt
  Mit Zitat antworten Zitat
nahpets
(Gast)

n/a Beiträge
 
#5

Re: Handle Leak finden

  Alt 16. Jan 2009, 12:34
Hallo,
Zitat von uligerhardt:
MemProof konnte das WIMRE. Ich hab aber keine Ahnung, ob das Ding mit D2009 funktioniert.
Danke für den Link, mit dem Werkzeug habe ich jetzt zumindest eine potentielle Fehlerstelle finden können.
  Mit Zitat antworten Zitat
nahpets
(Gast)

n/a Beiträge
 
#6

Re: Handle Leak finden

  Alt 16. Jan 2009, 15:50
Hallo,

vermutlich weiche ich jetzt vom Thema ab.
Mit dem Process Monitor habe ich mal die Zugriffe auf die Registrierung von meinem "Problemprogramm" aufzeichnen lassen. Hier ein Auszug:
Code:
"16:24:11,4810803","x.exe","1","RegOpenKey","HKLM\System\CurrentControlSet\Control\ComputerName","REPARSE",""
"16:24:11,4810915","x.exe","1","RegOpenKey","HKLM\System\CurrentControlSet\Control\ComputerName","SUCCESS",""
"16:24:11,4811071","x.exe","1","RegOpenKey","HKLM\System\CurrentControlSet\Control\ComputerName\ActiveComputerName","SUCCESS",""
"16:24:11,4811236","x.exe","1","RegQueryValue","HKLM\System\CurrentControlSet\Control\ComputerName\ActiveComputerName\ComputerName",
"SUCCESS","Type: REG_SZ, Length: 24, Data: SERVER02"
"16:24:11,4811345","x.exe","1","RegCloseKey","HKLM\System\CurrentControlSet\Control\ComputerName\ActiveComputerName","SUCCESS",""
"16:24:11,4811427","x.exe","1","RegCloseKey","HKLM\System\CurrentControlSet\Control\ComputerName","SUCCESS",""
"16:24:11,4813242","x.exe","1","RegQueryKey","HKCU\Software\Classes","SUCCESS","Query: Name"
"16:24:11,4813368","x.exe","1","RegOpenKey","HKCU\Software\Classes\CLSID\{8BC3F05E-D86B-11D0-A075-00C04FB68820}","NAME NOT FOUND",""
"16:24:11,4813475","x.exe","1","RegOpenKey","HKCR\CLSID\{8BC3F05E-D86B-11D0-A075-00C04FB68820}","SUCCESS",""
"16:24:11,4813757","x.exe","1","RegCloseKey","HKCR\CLSID\{8BC3F05E-D86B-11D0-A075-00C04FB68820}","SUCCESS",""
"16:24:11,5036595","x.exe","1","RegOpenKey","HKLM\System\CurrentControlSet\Control\ComputerName","REPARSE",""
"16:24:11,5036776","x.exe","1","RegOpenKey","HKLM\System\CurrentControlSet\Control\ComputerName","SUCCESS",""
"16:24:11,5036976","x.exe","1","RegOpenKey","HKLM\System\CurrentControlSet\Control\ComputerName\ActiveComputerName","SUCCESS",""
"16:24:11,5037137","x.exe","1","RegQueryValue","HKLM\System\CurrentControlSet\Control\ComputerName\ActiveComputerName\ComputerName",
"SUCCESS","Type: REG_SZ, Length: 24, Data: SERVER02"
"16:24:11,5037253","x.exe","1","RegCloseKey","HKLM\System\CurrentControlSet\Control\ComputerName\ActiveComputerName","SUCCESS",""
Zuerst wird ein Schlüssel ComputerName geöffnet, gelesen und geschlossen. Dann wird eine Abfrage HKCU\Software\Classes gestartet und anschließend wird eine CLSID geöffnet und nicht gefunden. Zu beidem gibt es kein CloseKey.

An anderer Stelle im Protokoll sieht es bei einem RegQueryKey etwas anders aus:
Code:
"12:44:17,6022323","x.exe","1","RegQueryKey","HKCR\CLSID\{2206CDB0-19C1-11D1-89E0-00C04FD7A829}","SUCCESS","Query: Name"
"12:44:17,6022471","x.exe","1","RegOpenKey","HKCU\Software\Classes\CLSID\{2206CDB0-19C1-11D1-89E0-00C04FD7A829}\TreatAs",
"NAME NOT FOUND",""
"12:44:17,6022594","x.exe","1","RegOpenKey","HKCR\CLSID\{2206CDB0-19C1-11D1-89E0-00C04FD7A829}\TreatAs","NAME NOT FOUND",""
"12:44:17,6022691","x.exe","1","RegCloseKey","HKCR\CLSID\{2206CDB0-19C1-11D1-89E0-00C04FD7A829}","SUCCESS",""
Hier wird abgefragt, erfolglos gelesen und wieder geschlossen.

Wenn ich das Programm nun Stunden laufen lasse, dann nimmt die Zahl der Handles stetig zu. Der Process Explorer zeigt mir zu einem Teil der Handles an, dass sie zum Lesen der Registrierung dienen und zwar zu dem Schlüssel HKCU\Software\Classes, bei dem oben in dem Auszug zu sehen ist, dass das entsprechende RegCloseKey fehlt. Ich habe das ganze Protokoll durchgeschaut und keine Stelle gefunden, an der entsprechende RegCloseKey zu HKCU\Software\Classes auftauchen, so dass ich momentan davon ausgehe, dass mein Problem mit der Zunahme der Handles hier zu suchen ist.

Hat jemand eine Idee, wie ich herausfinden kann, welcher Teil der Software in der Registrierung Schlüssel aus dem Zweig HKCU\Software\Classes liest. Ich selbst lese mit Sicherheit keine Werte aus diesem Bereich.
  Mit Zitat antworten Zitat
Assertor

Registriert seit: 4. Feb 2006
Ort: Hamburg
1.296 Beiträge
 
Turbo C++
 
#7

Re: Handle Leak finden

  Alt 16. Jan 2009, 17:15
Hallo,

Zitat von nahpets:
vermutlich weiche ich jetzt vom Thema ab.
Leicht, da es nun weniger um das Grundsätzliche als um Dein Problem geht

Zitat von nahpets:
Zu beidem gibt es kein CloseKey.
Da bist Du glaube ich auf der falschen Fährte - RegCloseKey ist doch nur nötig, falls der Schlüssel durch RegOpenKey erfolgreich geöffnet wurde. Die Rückmeldung "NAME NOT FOUND" zeigt ja, es gibt diesen Unterschlüssel nicht.

Zitat von nahpets:
Hat jemand eine Idee, wie ich herausfinden kann, welcher Teil der Software in der Registrierung Schlüssel aus dem Zweig HKCU\Software\Classes liest. Ich selbst lese mit Sicherheit keine Werte aus diesem Bereich.
Am einfachsten ist bzgl. Delphi über die Suche in Dateien z.B. nach RegOpenKey zu suchen, dann z.B. im Source Verzeichnis von Delphi und in Deinen Komponentenverzeichnissen.

Da wirst Du schon schnell sehen, wie oft und an welchen Stellen auf die Registry zugegriffen wird. Da sind von VCL Datenbank-Funktionen und Forms.pas über die RTL (System.pas, Windows.pas) bis hin zu den Third-Party-Komponenten (hier z.B. bei TB2k, Indy etc.pp.).

Zurück zum Grundsätzlichen:
Ich bin jetzt etwas weiter mit der Suche des Leaks, einfach großzügig Code auskommentieren und per "Iterationsverfahren" wieder einschliessen, bis das Leak entsteht. Dann bei der gefundenen Stelle gegebenfalls in die entsprechende Unit gehen und das gleiche von vorn.

Aufwendig, aber in meinem Fall besser als ein vollständiges Code-Audit an THtmlViewer, was ja ~ 20.000 - 30.000 Zeilen sind

Gruß Assertor
Frederik
  Mit Zitat antworten Zitat
nahpets
(Gast)

n/a Beiträge
 
#8

Re: Handle Leak finden

  Alt 19. Jan 2009, 08:14
Hallo Assertor,

Deine Begründung ist nachvollziehbar. Das iterative Verfahren wende ich jetzt schon seit Wochen an und komme dem Problem nicht auf die Sprünge. Mit an sicherheitgrenzender Wahrscheinlichkeit liegt das Problem nicht im Quellcode. Ausgehend vom Ergebnis des iterativen Prozesses kann ich die Problemstelle auf einen Quelltextbereich von ca. 100 Zeilen eingrenzen. Wenn ich von dort per Debugger soweit hineingehe, wie es nur geht, komme ich nicht an Methoden vorbei, die auf die Registrierung zugreifen. Es werden aber einige Routinen aus der Windows.pas aufgerufen, die Methoden aus der advapi32.dll kapseln. Vermutlich liegt dort das Problem.
  Mit Zitat antworten Zitat
Assertor

Registriert seit: 4. Feb 2006
Ort: Hamburg
1.296 Beiträge
 
Turbo C++
 
#9

Re: Handle Leak finden

  Alt 19. Jan 2009, 22:28
Hi,

Zitat von nahpets:
Mit an sicherheitgrenzender Wahrscheinlichkeit liegt das Problem nicht im Quellcode. Ausgehend vom Ergebnis des iterativen Prozesses kann ich die Problemstelle auf einen Quelltextbereich von ca. 100 Zeilen eingrenzen. Wenn ich von dort per Debugger soweit hineingehe, wie es nur geht, komme ich nicht an Methoden vorbei, die auf die Registrierung zugreifen. Es werden aber einige Routinen aus der Windows.pas aufgerufen, die Methoden aus der advapi32.dll kapseln. Vermutlich liegt dort das Problem.
Manchmal können ja auch externe Anwendungen durch Hooks oder in den Prozess geladene Dlls (Virenscanner) Leaks verursachen. Auch (Desktop-)Tools von Grafikkartenherstellern machen dies manchmal.

Oder ein vergessenes ReleaseDC etc.pp.

Eine einfache Möglichkeit zum Finden von Handle Leaks gibt es also (derzeit) nicht.

Mit meinem Problem bin ich jetzt übrigens auch weiter: Es liegt an der Printers.pas der VCL.

Gruß Assertor
Frederik
  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 10:51 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