Speicherfresser mittels Debugger finden

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
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

Beitrag von jacdelad »

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.
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
Axolotl
Beiträge: 148
Registriert: 31.12.2008 16:34

Re: Speicherfresser mittels Debugger finden

Beitrag von Axolotl »

Hallo jacdelad,

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 
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.
Mostly running PureBasic <latest stable version and current alpha/beta> (x64) on Windows 11 Home
Benutzeravatar
Dadido3
Beiträge: 103
Registriert: 24.02.2007 22:15
Kontaktdaten:

Re: Speicherfresser mittels Debugger finden

Beitrag von Dadido3 »

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:
  • AllocateStructure (Im Programm müss alle Vorkommnisse von AllocateStructure mit _AllocateStructure ersetzt werden. Das betrifft aber nur AllocateStructure!)
  • FreeStructure
  • AllocateMemory
  • ReAllocateMemory
  • FreeMemory
Dabei wird alle 10 Sekunden eine Liste mit reservierten Speicherbereichen über den Debugger ausgegeben. Auch wird gemeldet, wenn versucht wird einen zuvor gelöschten oder unbekannten Speicherbereich nochmals zu löschen oder dessen größe zu verändern.

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.
Benutzeravatar
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

Beitrag von jacdelad »

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
Benutzeravatar
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

Beitrag von jacdelad »

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.
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
Benutzeravatar
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

Beitrag von jacdelad »

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?
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
Antworten