Hallo,
ich brauche mal einen weißen Rat zum Debugger. Ich habe ihn bisher nur rudimentär genutzt, deshalb Steg ich bei der Bedienung auf dem Schlauch.
Ich habe ein Programm das aus 31 Rechnern ausgeführt wird und dort ein paar Dinge überwacht und per Netzwerk kommuniziert. Auf 30 Rechnern läuft es problemlos, aber auf einem benutzt es mit der Zeit immer mehr RAM und vermutlich auch andere Ressourcen, was soweit geht, dass andere Programme den Start wegen Ressourcenmangels verweigern, sogar der Taskmanager. Deshalb würde ich gern per Debugger herausfinden wo das Leck ist, aber ich komme nicht so richtig damit klar.
Speicherfresser mittels Debugger finden
- jacdelad
- Beiträge: 348
- Registriert: 03.02.2021 13:39
- Computerausstattung: Ryzen 5800X, 108TB Festplatte, 32GB RAM, Radeon 7770OC
- Wohnort: Riesa
- Kontaktdaten:
Speicherfresser mittels Debugger finden
PureBasic 6.04/XProfan X4a/Embarcadero RAD Studio 11/Perl 5.2/Python 3.10
Windows 11/Ryzen 5800X/32GB RAM/Radeon 7770 OC/3TB SSD/11TB HDD
Synology DS1821+/36GB RAM/130TB
Synology DS920+/20GB RAM/54TB
Synology DS916+ii/8GB RAM/12TB
Windows 11/Ryzen 5800X/32GB RAM/Radeon 7770 OC/3TB SSD/11TB HDD
Synology DS1821+/36GB RAM/130TB
Synology DS920+/20GB RAM/54TB
Synology DS916+ii/8GB RAM/12TB
Re: Speicherfresser mittels Debugger finden
Hallo jacdelad,
ich nutze fast nur den Debug Befehl. Häufig im Macro wie unten.
Um den Überblick zu behalten kann man in den Macros noch mit den #PB_Compiler_* Constanten hilfreiche Infos einbinden.
Jetzt ein paar Vorschläge, direkt aus der Hüfte....
Generell programmiere ich immer defensiv. D.h. Alle zurückgegebenen Werte von Proceduren werden auf Fehler ausgewertet und durch Debug (manchmal auch durch Eigenkonstruktion LogWrite()) angezeigt.
Wenn man Speicher oder Ressourcen allociert dann auch wieder freigeben und das Verhalten gemäß oben prüfen!
Für deinen Fall könnte auch der "Remote debugging with the standalone debugger" eine spannende Konfiguration sein. (Da bin ich aber nicht intensiv genug eingestiegen.)
Besser kann ich jetzt spontan nicht helfen. Ggf. kommt ja noch einer der Profis mit ein paar Ideen.
ich nutze fast nur den Debug Befehl. Häufig im Macro wie unten.
Code: Alles auswählen
Macro DQ
"
EndMacro
Macro RectToText(rcRect, sSep=", ") ; sSep separated text
Str(rcRect\left) + sSep + Str(rcRect\top) + sSep + Str(rcRect\right) + sSep + Str(rcRect\bottom)
EndMacro
Macro InspectRect(rcRect)
DQ#rcRect#DQ + " = " + RectToText(rcRect)
EndMacro
; irgendwo im code wenn es um ein rc.RECT geht, wie beispielsweise bei GetWindowRect_()
Debug InspectRect(rc)
Um den Überblick zu behalten kann man in den Macros noch mit den #PB_Compiler_* Constanten hilfreiche Infos einbinden.
Code: Alles auswählen
Macro DebugEx(sText)
Debug sText + " - " + #PB_Compiler_Procedure + "()"
EndMacro
Generell programmiere ich immer defensiv. D.h. Alle zurückgegebenen Werte von Proceduren werden auf Fehler ausgewertet und durch Debug (manchmal auch durch Eigenkonstruktion LogWrite()) angezeigt.
Wenn man Speicher oder Ressourcen allociert dann auch wieder freigeben und das Verhalten gemäß oben prüfen!
Für deinen Fall könnte auch der "Remote debugging with the standalone debugger" eine spannende Konfiguration sein. (Da bin ich aber nicht intensiv genug eingestiegen.)
Besser kann ich jetzt spontan nicht helfen. Ggf. kommt ja noch einer der Profis mit ein paar Ideen.
Mostly running PureBasic <latest stable version and current alpha/beta> (x64) on Windows 11 Home
Re: Speicherfresser mittels Debugger finden
Der Debugger alleine ist nicht sonderlich hilfreich beim aufspüren von Speicherlecks von dynamischen Speicherbereichen.
Ich habe für diesen Fall mal ein >> Include << geschrieben welches jeden der folgenden Aufrufe überwacht:
Um es zu verwenden, einfach am Anfang deines Programmes inkludieren oder reinkopieren. Wenn die ausgegebene Liste mit der Zeit immer größer wird, dann hast du mit ziemlicher Sicherheit ein (selbstgemachtes) Speicherleck. Mit Hilfe der ausgegebenen Liste kann man dann relativ einfach die Zeile von AllocateStructure bzw. AllocateMemory finden, dessen Speicher vergessen wurde freizugeben.
Natürlich setzt das voraus, dass dein Problem durch nicht mehr gelöschte dynamische Speicherbereiche entsteht. Falls du andere dynamische Ressourcen reservierst (z.B. Bilder) hilft das Include nicht beim Aufspüren von deren Speicherlecks, aber es ließe sich dahingehend erweitern. Für Listen und Maps kannst du natürlich die Anzahl der Elemente direkt im Debugger ermitteln.
Der Code hat noch Luft für Verbesserungen. Man könnte noch zusätzlich zur Zeilennummer den Namen des aktuellen Quellcodes speichern. Auch ist die Ausgabe durch den Debugger eventuell ungünstig, aber es ist nicht allzu schwer die Ausgabe in eine Datei umzubiegen. Ich hoffe der Code hilft, wenn auch nur als Basis.
Ich habe für diesen Fall mal ein >> Include << geschrieben welches jeden der folgenden Aufrufe überwacht:
- AllocateStructure (Im Programm müss alle Vorkommnisse von AllocateStructure mit _AllocateStructure ersetzt werden. Das betrifft aber nur AllocateStructure!)
- FreeStructure
- AllocateMemory
- ReAllocateMemory
- FreeMemory
Um es zu verwenden, einfach am Anfang deines Programmes inkludieren oder reinkopieren. Wenn die ausgegebene Liste mit der Zeit immer größer wird, dann hast du mit ziemlicher Sicherheit ein (selbstgemachtes) Speicherleck. Mit Hilfe der ausgegebenen Liste kann man dann relativ einfach die Zeile von AllocateStructure bzw. AllocateMemory finden, dessen Speicher vergessen wurde freizugeben.
Natürlich setzt das voraus, dass dein Problem durch nicht mehr gelöschte dynamische Speicherbereiche entsteht. Falls du andere dynamische Ressourcen reservierst (z.B. Bilder) hilft das Include nicht beim Aufspüren von deren Speicherlecks, aber es ließe sich dahingehend erweitern. Für Listen und Maps kannst du natürlich die Anzahl der Elemente direkt im Debugger ermitteln.
Der Code hat noch Luft für Verbesserungen. Man könnte noch zusätzlich zur Zeilennummer den Namen des aktuellen Quellcodes speichern. Auch ist die Ausgabe durch den Debugger eventuell ungünstig, aber es ist nicht allzu schwer die Ausgabe in eine Datei umzubiegen. Ich hoffe der Code hilft, wenn auch nur als Basis.
- jacdelad
- Beiträge: 348
- Registriert: 03.02.2021 13:39
- Computerausstattung: Ryzen 5800X, 108TB Festplatte, 32GB RAM, Radeon 7770OC
- Wohnort: Riesa
- Kontaktdaten:
Re: Speicherfresser mittels Debugger finden
Ah danke, das werde ich mal ausprobieren. Irgendwo muss ich ja anfangen und je mehr ich ausschließen kann desto enger wird der Kreis der Verdächtigen.
PureBasic 6.04/XProfan X4a/Embarcadero RAD Studio 11/Perl 5.2/Python 3.10
Windows 11/Ryzen 5800X/32GB RAM/Radeon 7770 OC/3TB SSD/11TB HDD
Synology DS1821+/36GB RAM/130TB
Synology DS920+/20GB RAM/54TB
Synology DS916+ii/8GB RAM/12TB
Windows 11/Ryzen 5800X/32GB RAM/Radeon 7770 OC/3TB SSD/11TB HDD
Synology DS1821+/36GB RAM/130TB
Synology DS920+/20GB RAM/54TB
Synology DS916+ii/8GB RAM/12TB
- jacdelad
- Beiträge: 348
- Registriert: 03.02.2021 13:39
- Computerausstattung: Ryzen 5800X, 108TB Festplatte, 32GB RAM, Radeon 7770OC
- Wohnort: Riesa
- Kontaktdaten:
Re: Speicherfresser mittels Debugger finden
Ich habe tatsächlich einen Abschnitt gefunden, bei dem ein Speicher reserviert und unter bestimmten Umständen nicht freigegeben wurde. Vielleicht war das schon alles.
Die pbi von @Dadido3 geht auch ganz gut, simpel und schlicht. Ich hab sie minimal angepasst, damit man bei der Übergabe eines zweiten Parameters bei AllocateMemory keine Fehlermeldung bekommt.
Vielen Dank.
Die pbi von @Dadido3 geht auch ganz gut, simpel und schlicht. Ich hab sie minimal angepasst, damit man bei der Übergabe eines zweiten Parameters bei AllocateMemory keine Fehlermeldung bekommt.
Vielen Dank.
PureBasic 6.04/XProfan X4a/Embarcadero RAD Studio 11/Perl 5.2/Python 3.10
Windows 11/Ryzen 5800X/32GB RAM/Radeon 7770 OC/3TB SSD/11TB HDD
Synology DS1821+/36GB RAM/130TB
Synology DS920+/20GB RAM/54TB
Synology DS916+ii/8GB RAM/12TB
Windows 11/Ryzen 5800X/32GB RAM/Radeon 7770 OC/3TB SSD/11TB HDD
Synology DS1821+/36GB RAM/130TB
Synology DS920+/20GB RAM/54TB
Synology DS916+ii/8GB RAM/12TB
- jacdelad
- Beiträge: 348
- Registriert: 03.02.2021 13:39
- Computerausstattung: Ryzen 5800X, 108TB Festplatte, 32GB RAM, Radeon 7770OC
- Wohnort: Riesa
- Kontaktdaten:
Re: Speicherfresser mittels Debugger finden
Das Problem scheint noch nicht ganz gefixt zu sein.
Ich weiß, dass ich per Windows-API auslesen kann welche Objekte ich im Speicher hab und wie groß die sind. Gibt es da schon einen vorgefertigten Quelltext?
Ich weiß, dass ich per Windows-API auslesen kann welche Objekte ich im Speicher hab und wie groß die sind. Gibt es da schon einen vorgefertigten Quelltext?
PureBasic 6.04/XProfan X4a/Embarcadero RAD Studio 11/Perl 5.2/Python 3.10
Windows 11/Ryzen 5800X/32GB RAM/Radeon 7770 OC/3TB SSD/11TB HDD
Synology DS1821+/36GB RAM/130TB
Synology DS920+/20GB RAM/54TB
Synology DS916+ii/8GB RAM/12TB
Windows 11/Ryzen 5800X/32GB RAM/Radeon 7770 OC/3TB SSD/11TB HDD
Synology DS1821+/36GB RAM/130TB
Synology DS920+/20GB RAM/54TB
Synology DS916+ii/8GB RAM/12TB