Wie nach memory leaks suchen?



  • Einen wunderschönen Guten Morgen:)

    @Quiche-Lorraine sagte in Wie nach memory leaks suchen?:

    Naja, sobald die Speicheranforderung kontinuierlich größer werden, hast du ein Memory Leak.
    Und sorry, ich muss nochmals nachfragen: Ist es definitiv ein Memory-Leak? Kannst du beispielsweise eine Aktion wiederholen und die Speicheranforderungen steigen stetig? Kannst du so z.B. 10MByte verballern?
    Ich habe nämlich schon einige angebliche Speicherlöcher gesehen, welche keine waren, sondern nur eine Eigenarten der C Runtime, Windows oder auch der WinAPI. Denn du nutzt die MFC, welche auf der WinAPI basiert. Und die WinAPI ist tückisch.
    Hast du den Visual Leak Detector for Visual C++ ausprobiert? Alternativ könntest du auch noch DebugDiag ausprobieren.

    ich konnte das Memory-Leak lokalisieren (durch hinweise des cppckecks), also ja es war wirklich so, dass in ner loop (all 200ms, 2byte allokiert wurden aber nicht mehr frei gegeben wurden. Jetzt ist der Memory-Dump weg.

    @hustbaer sagte in Wie nach memory leaks suchen?:

    Du kannst einen Weekly-Build von Dr. Memory probieren. Oder eine andere Windows Version. Dr. Memory hat da leider manchmal Probleme die ich nicht ganz nachvollziehen kann. Die haben z.B. einen eigenen Loader drinnen mit dem sie ihre "Client DLL" laden. Warum auch immer, keine Ahnung. Und dieser Loader kann auf deinem OS wohl die Funktion MoveFileExW nicht finden.
    Du kannst auch einen Case hier aufmachen: https://github.com/DynamoRIO/dynamorio/issues

    ok dann probiere ich mal ein andere release aus... danke danke

    @Finnegan sagte in Wie nach memory leaks suchen?:

    Ich habe keine Ahnung von der Software, aber Windows hat meines Wissens keine KERNALBASE.dll sondern eine KernelBase.dll. Darin findet sich auch die MoveFileExW-Funktion, und dass bereits seit Windows XP. Sieht mir irgendwie nach einem Tippfehler in deiner Version aus. Schon etwas komisch, denn gerade bei so einem Fehler würde ich erwarten, dass er bei Tests sehr schnell auffällt. Probier's mal mit dem Vorschlag von @hustbaer, eine andere Version zu nehmen. Das schaut sehr danach aus, als wäre ein Bug-Report angebracht.

    das war ein Schreibfehler meinerseits "KERNALBASE.dll" ich habe den Text aus der MsgBox abgetippt.



  • Achje, ja, die tollen MessageBoxen wo Ctrl+C nicht funktioniert. Das sollte MS auch mal fixen.



  • Was mir noch aufgefallen ist, ich mache viel GID Kram in meiner MFC App, und mir war nicht klar,
    dass ich für jedes GDI Object .. hier CPen/CBrush.. die "DeleteObject" Method explizt aufrufen muss, dachte das mach dann deren Dtor... und Memory Dumpy bekam ich da auch nicht...

    CPen blackPen;
    blackPen.CreatePen(PS_SOLID,1,RGB(0,0,0));
    CBrush brush(atol(m_Data.GetAt(i-1,2)));
    Cpen* poldPen = pDC->SelectObject(&blackPen);
    CBrush * poldBrush= pDC->SelectObject(brush);
    ...
    
    pDC->SelectObject(poldPen );
    pDC->SelectObject(poldBrush );
    brush.DeleteObject();
    blackPen.DeleteObject();
    


  • @SoIntMan sagte in Wie nach memory leaks suchen?:

    und mir war nicht klar,
    dass ich für jedes GDI Object .. hier CPen/CBrush.. die "DeleteObject" Method explizt aufrufen muss, dachte das mach dann deren Dtor... und Memory Dumpy bekam ich da auch nicht...

    CPen blackPen;
    blackPen.CreatePen(PS_SOLID,1,RGB(0,0,0));
    CBrush brush(atol(m_Data.GetAt(i-1,2)));
    pDC->SelectObject(&blackPen);
    pDC->SelectObject(brush);
    ...
    brush.DeleteObject();
    blackPen.DeleteObject();
    

    Wieso meinst du dass du das musst bzw. dass der von dir gezeigte Code korrekt ist?

    Soweit ich weiss sollte das eher so aussehen:

    CPen blackPen;
    blackPen.CreatePen(PS_SOLID,1,RGB(0,0,0));
    CBrush brush(atol(m_Data.GetAt(i-1,2)));
    CPen* originalPen = pDC->SelectObject(&blackPen);
    CBrush* originalBrush = pDC->SelectObject(&brush);
    ...
    pDC->SelectObject(originalPen);
    pDC->SelectObject(originalBrush);
    

    Siehe https://docs.microsoft.com/en-us/cpp/mfc/selecting-a-graphic-object-into-a-device-context?view=msvc-160



  • @hustbaer sagte in Wie nach memory leaks suchen?:

    Wieso meinst du dass du das musst bzw. dass der von dir gezeigte Code korrekt ist?
    Soweit ich weiss sollte das eher so aussehen:

    CPen blackPen;
    blackPen.CreatePen(PS_SOLID,1,RGB(0,0,0));
    CBrush brush(atol(m_Data.GetAt(i-1,2)));
    CPen* originalPen = pDC->SelectObject(&blackPen);
    CBrush* originalBrush = pDC->SelectObject(&brush);
    ...
    pDC->SelectObject(originalPen);
    pDC->SelectObject(originalBrush);

    Siehe https://docs.microsoft.com/en-us/cpp/mfc/selecting-a-graphic-object-into-a-device-context?view=msvc-160

    ja siehe oben, das habe ich noch vergessen im code-snipped (SelectObject(orgObjects).. aber trotzdem mit DeleteObject

    https://forums.codeguru.com/showthread.php?115114-CPen-CBrush-DeleteObject-minimizing-memory-leaks-and-releasing-resources

    EDIT: hmmm.. was is nun richtig....!?



  • @SoIntMan sagte in Wie nach memory leaks suchen?:

    @hustbaer sagte in Wie nach memory leaks suchen?:

    Wieso meinst du dass du das musst bzw. dass der von dir gezeigte Code korrekt ist?
    Soweit ich weiss sollte das eher so aussehen:

    CPen blackPen;
    blackPen.CreatePen(PS_SOLID,1,RGB(0,0,0));
    CBrush brush(atol(m_Data.GetAt(i-1,2)));
    CPen* originalPen = pDC->SelectObject(&blackPen);
    CBrush* originalBrush = pDC->SelectObject(&brush);
    ...
    pDC->SelectObject(originalPen);
    pDC->SelectObject(originalBrush);

    Siehe https://docs.microsoft.com/en-us/cpp/mfc/selecting-a-graphic-object-into-a-device-context?view=msvc-160

    ja siehe oben, das habe ich noch vergessen im code-snipped (SelectObject(orgObjects).. aber trotzdem mit DeleteObject

    https://forums.codeguru.com/showthread.php?115114-CPen-CBrush-DeleteObject-minimizing-memory-leaks-and-releasing-resources

    EDIT: hmmm.. was is nun richtig....!?

    Die schreiben doch auch dass das DeleteObject nicht nötig ist:

    Not that it makes much difference (I consider it good style to call CGdiObject::DeleteObject explicitly) but the destructor for the individual object types will delete the object automatically.
    Therefore there is no actual need to call DeleteObject if you're declaring a local GDI object inside a loop (providing you remember to deselect it from the DC first) as it will be called automatically when the object goes out of scope.

    Gut, der meint dass er es "good style" findet trotzdem selbst DeleteObject aufzurufen. Ich bin da ganz anderer Meinung. Ich finde dass das ganz schlechter Stil ist. Unnötiger Code bremst bloss beim Lesen und ist - gerade für Leute die sich noch nicht perfekt mit dem verwendeten Framework auskennen - verwirrend/schädlich. Weil man normalerweise halt nicht davon ausgeht dass jemand was hinschreibt was völlig redundant ist. Und daher kann man dann schnell annehmen, dass es halt nicht redundant ist. Was ja wie gesagt nicht stimmt.

    Darüber ob die Objekte jetzt automatisch gelöscht werden oder nicht besteht aber kein Zweifel. Das steht da auch klar in dem Thread dass sie das werden.



  • @SoIntMan sagte in Wie nach memory leaks suchen?:

    Nun habe ich beim schließen der App Memoryleaks:

    wenn ein prozess beendet wird, erlischt auch sein virtueller adressraum.

    d.h ein normales windows-programm kann üblicherweise keine memLeaks erzeugen, die das ganze system beeinträchtigen.



  • @Foulpelz sagte in Wie nach memory leaks suchen?:

    d.h ein normales windows-programm kann üblicherweise keine memLeaks erzeugen, die das ganze system beeinträchtigen.

    Doch.



  • @Foulpelz

    d.h ein normales windows-programm kann üblicherweise keine memLeaks erzeugen, die das ganze system beeinträchtigen.

    Ähm. Was wenn das Programm ein bisschen länger als "nur ganz kurz" läuft? Wie z.B. alle Service-Prozesse und die meisten Anwendungen? Also quasi so ziemlich alles bis auf manche Commandline-Tools?

    Ne, sorry, die Aussage ist wirklich total falsch.



  • Ich weiß nicht obs noch geht, aber es war vor einiger Zeit noch möglich mit msvc und als Debug Build soviel Speicher zu allozieren und nicht freizugeben wie man wollte. Das ist definitiv einschneidend für das System 😅



  • @hustbaer sagte in Wie nach memory leaks suchen?:

    Die schreiben doch auch dass das DeleteObject nicht nötig ist:

    Not that it makes much difference (I consider it good style to call CGdiObject::DeleteObject explicitly) but the destructor for the individual object types will delete the object automatically.
    Therefore there is no actual need to call DeleteObject if you're declaring a local GDI object inside a loop (providing you remember to deselect it from the DC first) as it will be called automatically when the object goes out of scope.

    Gut, der meint dass er es "good style" findet trotzdem selbst DeleteObject aufzurufen. Ich bin da ganz anderer Meinung. Ich finde dass das ganz schlechter Stil ist. Unnötiger Code bremst bloss beim Lesen und ist - gerade für Leute die sich noch nicht perfekt mit dem verwendeten Framework auskennen - verwirrend/schädlich. Weil man normalerweise halt nicht davon ausgeht dass jemand was hinschreibt was völlig redundant ist. Und daher kann man dann schnell annehmen, dass es halt nicht redundant ist. Was ja wie gesagt nicht stimmt.
    Darüber ob die Objekte jetzt automatisch gelöscht werden oder nicht besteht aber kein Zweifel. Das steht da auch klar in dem Thread dass sie das werden.

    Danke , ja ich finde das auch kein guter Stil, nix desto trotz habe ich es einfach mal so gemacht, um in meinen WnCE build die memory leak problematik einzugrenzen.

    @Foulpelz sagte in Wie nach memory leaks suchen?:

    wenn ein prozess beendet wird, erlischt auch sein virtueller adressraum.
    d.h ein normales windows-programm kann üblicherweise keine memLeaks erzeugen, die das ganze system beeinträchtigen.

    Doch, genau das geschieht:) Meine Anwendung ließt zyklisch Mess-Daten via Tcp/ip und zeigt diese Daten dann via GDI gemale an:) Und wenn ich das Ganze dann ne Nacht laufen lasse (auf WinCE) erscheint ne Meldung Memory low.. alle anderen Anwendung sind eingefroren etc. Nichts geht mehr..

    Das Problem ist, dass ich aber keine Memory leaks bzw. keine Dumps (beim beenden der Anwendung ) mehr bekomme, wenn ich sie auf Win32 system im Debugger kompiliert laufen lasse.

    Ich verwendet quasi die selbe Codebase als ein CDialogHost, welches ich einmal in Win32 App und einmal in WinCE App verwenden/kompilieren kann.

    Leider habe ich vermutlich immer noch memory-leaks.. aber das kann ich schlecht auf dem WinCE device debuggen, ich ging mal davon aus dass wenn ich keine memoryDumps im Win32 target mehr bekomme ich dann in WinCE gut weg komme.. aber falsch gedacht😅



  • @SoIntMan Hast du immer noch ein Leak? Oder ist nun Ruhe?



  • Ich habe ein kleines Tool geschrieben hier , einfach:

    • Kopiere MemoryLeakManager.hpp Header
    • #include "MemoryLeakManager.hpp"
    • am anfang deine Programm schreibe:
    int dummy = 0;
    g_stackTop = &dummy;
    
    • am ende aufruf:
    CollectGarbage();
    

    das Tool wird dir sagen, wo du Memory Leak gemacht hast.



  • @muazsh

    #define new new(__FILE__, __LINE__)
    

    Mit nem #define für new kann das die MSVC Runtime auch selbst.
    Einfach

    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif
    

    in alle .cpp Files nach allen #includes reinschreiben, und passt.

    ps: Dein Code ist nicht Thread-safe.



  • @hustbaer sagte in Wie nach memory leaks suchen?:

    @SoIntMan Hast du immer noch ein Leak? Oder ist nun Ruhe?

    Hi Hustbear, ich weiß es nicht 😞 also wie erwähnt bekomme ich keine Memory Dumps mehr (kann das ja nur in der Win32 Debug vs2008 Output sehen)
    Wenn ich dann auf das Target auf WinCE release ARM wechsel und das auf dem WinCE gerät Laufen lasse (über 24h) dann läuft mir der Speicher voll, aber ich habe auf WinCE keine diagnose tools um das zu prüfen.

    Weißt Du, Kennst du ein Diagnose Tool für WinCE um sowas zu prüfen?:)

    EDIT: hmm .. vll. hilft mir das https://sourceforge.net/projects/crtdbg4wince/ weiter

    @muazsh sagte in Wie nach memory leaks suchen?:

    Ich habe ein kleines Tool geschrieben hier , einfach:

    Kopiere MemoryLeakManager.hpp Header
    #include "MemoryLeakManager.hpp"
    am anfang deine Programm schreibe:

    int dummy = 0;
    g_stackTop = &dummy;

    am ende aufruf:

    CollectGarbage();

    das Tool wird dir sagen, wo du Memory Leak gemacht hast.

    hammer danke, ABER damit kann ich dann auch nur in der Win32 Target leaks suchen, finde ich da mehr als der Vs2008 Memory Dump?



  • Wenn du auf WinCE einen Memory Leak hast, wirst du den auch in den Win32 Targets haben.
    Es kann natürlich auch sein, das freigegeben würde, aber das zu spät passiert (ist mir mal beim laden von Frames aus 'nem Video Stream passiert). Das ist dann kein Leak im klassichen Sinn, macht aber keinen Unterschied, weil der Speicher trotzdem irgendwann voll ist.

    Was mir spontan einfallen würde, ist: Mit GetProcessMemoryInfo für Windows an verschiedenen Stellen Informationen zum Speichererbrauch deines Prozesses auszulesen und in ein log File zu schreiben.

    Oder, testweise einen eigenen Memory Manager einhängen, und new und delete überschreiben. Da könntest du auch den Speicher so beschränken, dass du mit dem Win32 Target in das selbe Problem läufst, wie auf WinCE. Und, im Überlauf fall, könntest du einen Stacktrace ausgeben lassen (z.B. mit https://www.boost.org/doc/libs/1_66_0/doc/html/stacktrace/getting_started.html#stacktrace.getting_started.how_to_print_current_call_stack)



  • Wieviel RAM hat den das WinCE Gerät?

    Wenn es z.b. nur 1GB Ram hat und aber auf deinem Development Maschine das ganze nach 24h mehr als 1GB Ram braucht dann hast du einen Hinweis was los ist.



  • @SoIntMan sagte in Wie nach memory leaks suchen?:

    hammer danke, ABER damit kann ich dann auch nur in der Win32 Target leaks suchen, finde ich da mehr als der Vs2008 Memory Dump?

    Nein, weniger.



  • @Schlangenmensch sagte in Wie nach memory leaks suchen?:

    Wenn du auf WinCE einen Memory Leak hast, wirst du den auch in den Win32 Targets haben.

    ok das is beruhigend:) ich logge einfach mal die speicherverbrauch mit.

    @firefly sagte in Wie nach memory leaks suchen?:

    Wieviel RAM hat den das WinCE Gerät?
    Wenn es z.b. nur 1GB Ram hat und aber auf deinem Development Maschine das ganze nach 24h mehr als 1GB Ram braucht dann hast du einen Hinweis was los ist.

    das ding hat 200MB Ram. Also nich viel.

    @hustbaer sagte in Wie nach memory leaks suchen?:

    @SoIntMan sagte in Wie nach memory leaks suchen?:

    hammer danke, ABER damit kann ich dann auch nur in der Win32 Target leaks suchen, finde ich da mehr als der Vs2008 Memory Dump?

    Nein, weniger.

    Bedeutet es denn dass wenn ich keine "Memory-dumps" bekomme, Ich memory Leaks frei bin?



  • Process Hacker ist auch noch ein interessantes Tool, das den Windows Task Manager ersetzt. Damit kann man sich detaillierte Eigenschaften eines Prozesses anschauen und in der Statistik gucken, ob einem zB Windows Handles weglaufen. Damit hat man zumindest einen Indiz auf die Ursache eines Resource Leaks.


Anmelden zum Antworten