Laufzeitbibliothek als "Multithreaded DLL" sorgt für Memory Leak



  • Moment, ich mach mal ein kleines Testprojekt ...

    ChrisM



  • So, hab meine DLL jetzt auf das wesentliche minimiert (alle Dateien von der Erstellung ausgeschlossen, außer der Hauptdatei und in der alles außer Konstruktor, Destruktor und der statischen Memberfunktion, die die Leaks dumpen soll, auskommentiert) und er findet keine Leak mehr!!
    Ich aktivier jetzt wieder langsam alles und sag dann, worans lag, ok?

    ChrisM



  • Komisch, bei den harmlosesten Klassen, kommen wieder Memory Leaks. Ich hab z.B. Color.cpp und Color.h wieder kompilieren lassen und jetzt ist das Leak wieder da. Die Dateien sehen so aus:

    Color.h

    #ifndef THETAENGINEINCLUDE_COLOR
    #define THETAENGINEINCLUDE_COLOR
    
    #include "Global.h"
    
    class thetaColor
    {
    public:
        THETADLL thetaColor();
        THETADLL thetaColor(unsigned long dwRed, unsigned long dwGreen, unsigned long dwBlue, unsigned long dwAlpha);
        THETADLL thetaColor(unsigned long dwARGB);
    
        THETADLL void Set(unsigned long dwRed, unsigned long dwGreen, unsigned long dwBlue, unsigned long dwAlpha);
        THETADLL void SetRed(unsigned long dwRed);
        THETADLL void SetGreen(unsigned long dwGreen);
        THETADLL void SetBlue(unsigned long dwBlue);
        THETADLL void SetAlpha(unsigned long dwAlpha);
    
        THETADLL unsigned long dwGetAsDWORD() const;
        THETADLL unsigned long dwGetRed() const;
        THETADLL unsigned long dwGetGreen() const;
        THETADLL unsigned long dwGetBlue() const;
        THETADLL unsigned long dwGetAlpha() const;
    
    protected:
        unsigned long m_dwRed, m_dwGreen, m_dwBlue, m_dwAlpha;
    };
    
    #endif
    

    Color.cpp

    #include "Color.h"
    
    thetaColor::thetaColor()
    {
        m_dwRed = m_dwGreen = m_dwBlue = m_dwAlpha = 0;
    }
    
    thetaColor::thetaColor(unsigned long dwRed, unsigned long dwGreen, unsigned long dwBlue,
                           unsigned long dwAlpha)
    {
        m_dwRed = dwRed;
        m_dwGreen = dwGreen;
        m_dwBlue = dwBlue;
        m_dwAlpha = dwAlpha;
    }
    
    thetaColor::thetaColor(unsigned long dwARGB)
    {
        // to do
    }
    
    void thetaColor::Set(unsigned long dwRed, unsigned long dwGreen, unsigned long dwBlue,
                    unsigned long dwAlpha)
    {
        m_dwRed = dwRed;
        m_dwGreen = dwGreen;
        m_dwBlue = dwBlue;
        m_dwAlpha = dwAlpha;
    }
    
    void thetaColor::SetRed(unsigned long dwRed) { m_dwRed = dwRed; }
    void thetaColor::SetGreen(unsigned long dwGreen) { m_dwGreen = dwGreen; }
    void thetaColor::SetBlue(unsigned long dwBlue) { m_dwBlue = dwBlue; }
    void thetaColor::SetAlpha(unsigned long dwAlpha) { m_dwAlpha = dwAlpha; }
    
    unsigned long thetaColor::dwGetAsDWORD() const
    {
        // to do
        return 0x00000000;
    }
    
    unsigned long thetaColor::dwGetRed() const { return m_dwRed; }
    unsigned long thetaColor::dwGetGreen() const { return m_dwGreen; }
    unsigned long thetaColor::dwGetBlue() const { return m_dwBlue; }
    unsigned long thetaColor::dwGetAlpha() const { return m_dwAlpha; }
    

    THETADLL ist einfach ein #define für __declspec(dllexport)! (im DLL-Projekt, sonst natürlich dllimport)

    ChrisM



  • Kann dir da leider nicht weiterhelfen, aber durchsuch mal Google Groups dannach.

    z.B. so :p



  • Schön, aber mein ganzer STL-Teil ist ja eh auskommentiert und in Color.cpp kommt ja kein String vor!

    ChrisM



  • Mach uns doch mal das kleinst-mögliche Beispiel fertig, wo diese Leaks dann immer noch entstehen, so das wir selbst mal rumspielen können. Am besten, wenn es geht, in einem Projekt (also ohne DLL) und alles in eine Datei. 🙂



  • Ja, aber ich kanns net rekonstruieren, ich versuch jetzt mal durch Auskommentieren in Color.cpp den Fehlergrund zu suchen und dann sag ich euch, woran es liegt. 🙂

    ChrisM



  • Oder lad das Ding mal auf deinen Homepage-Server und lass uns mitprobieren.



  • Hab das Problem gefunden: Ich kriege die Leak-Warnung, wenn ich irgendwo std::string verwende (also kommts doch von der STL). Das komische ist nur, ich kriege die Warnungen nicht, wenn ich nur string inkludiere, aber std::string nicht verwende (noch nicht so komisch), aber erst hab ich gedacht, es sind vielleicht statische Member von std::string, aber das kann ja nicht sein, denn die würden ja erst erzeugt werden, wenn die Funktion aufgerufen wird, aber meine Testfunktion, die std::string verwendet, wird nirgends aufgerufen!

    ChrisM



  • *Code will* :p



  • Gerne:

    void Test()
    {
        std::string strTest;
    }
    

    Im Header wird diese Funktion in die DLL exportiert, aber sie wird nirgends aufgerufen. Trotzdem seh ich die beiden Memory Leaks, kommentier ich sie aus (gibt keinen Fehler, wird ja nirgends aufgerufen) hab ich keine Memory Leaks mehr!

    ChrisM



  • ok, danke. Aber kannst du das Beispiel bitte hochladen? Ich hab keine Lust das ganze zusammenzubauen. 😃



  • OK: http://www.chrismandery.de/LeakTest.zip

    In der Main.cpp des Projektes der EXE stehen noch drei Zeilen Hinweise. 🙂

    ChrisM



  • OK, thx.
    Bei mir wird allerdings nur der Leak gedumpt den du mit int *pLeak = new int; erzeugt hast. VC++ .NET 7



  • Post mal deinen Debugoutput, meiner ist:

    "ntdll.dll" wurde geladen. Es wurden keine entsprechenden Symbolinformationen gefunden.
    "C:\WINDOWS\system32\kernel32.dll" wurde geladen. Es wurden keine entsprechenden Symbolinformationen gefunden.
    Geladene Symbole für "C:\Dokumente und Einstellungen\Chris\Eigene Dateien\Programmieren\Projekte\LeakTest\Exe\LeakTest.dll"
    Geladene Symbole für "C:\WINDOWS\system32\MSVCP60D.DLL"
    Geladene Symbole für "C:\WINDOWS\system32\MSVCRTD.DLL"
    Detected memory leaks!
    Dumping objects ->
    {50} normal block at 0x00420040, 4 bytes long.
    Data: < > CD CD CD CD
    {43} normal block at 0x004200A0, 33 bytes long.
    Data: < C > 00 43 00 CD CD CD CD CD CD CD CD CD CD CD CD CD
    {42} normal block at 0x004200F0, 40 bytes long.
    Data: < |L > 14 7C 4C 10 16 00 00 00 00 00 00 00 00 00 00 00
    Object dump complete.
    Thread 0x88 wurde mit Code 0 (0x0) beendet.
    Das Programm "C:\Dokumente und Einstellungen\Chris\Eigene Dateien\Programmieren\Projekte\LeakTest\Exe\Debug\Exe.exe" wurde mit Code 0 (0x0) beendet.

    ChrisM



  • 'Exe.exe': 'C:\LeakTest\Exe\Debug\Exe.exe' geladen, Symbole geladen.
    'Exe.exe': 'C:\WINDOWS\system32\ntdll.dll' geladen, Symbole geladen.
    'Exe.exe': 'C:\WINDOWS\system32\kernel32.dll' geladen, Symbole geladen.
    'Exe.exe': 'C:\LeakTest\Exe\Debug\LeakTest.dll' geladen, Symbole geladen.
    'Exe.exe': 'C:\WINDOWS\system32\msvcp70d.dll' geladen, Symbole geladen.
    'Exe.exe': 'C:\WINDOWS\system32\msvcr70d.dll' geladen, Symbole geladen.
    Detected memory leaks!
    Dumping objects ->
    {85} normal block at 0x00325318, 4 bytes long.
     Data: <    > CD CD CD CD 
    Object dump complete.
    Das Programm "[1628] Exe.exe: Systemeigen" wurde mit Code 0 (0x0) beendet.
    


  • Komisch!
    Was würdest du jetzt machen? Einfach ignorieren oder kein std::string mehr verwenden?

    ChrisM



  • Hab mir jetzt nochmal den Visual C++ 6 installiert um mir das Problem anzuschauen. Aber deinen Code hätte man noch um einiges verkürzen können. Ich denke mal, das es einfach ein Bug ist. Mit Visual C++ 7 tritt der Fehler auch bei mir nicht auf.

    #include <string>
    #include <crtdbg.h>
    
    int main() {
        std::string s;
        _CrtDumpMemoryLeaks();
        return 0;
    }
    


  • Also ich möchte nicht auf std::string verzichten wollen. :p 😃
    Aber jetzt hab ich mir die Newsgroup-Artikel nochmal genauer angeschaut:

    Link zum Artikel

    1. The first line of your "main" function should always read:

    _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

    Leaks will be dumped automatically on program termination -- no need to
    call _CrtDumpMemoryLeaks().

    Dann klappts, jedenfalls bei mir. 😃



  • Bei mir auch!! 😃

    Danke, ihr seid echt super genial!! 😃 😃

    ChrisM


Anmelden zum Antworten