开发者

Trying to understand a mem leak

I'm working with VLD (Visual Leak Detector), and it detects some mem leaks. I'm trying to understand why this is a mem leak for VLD. It could be a false positive?

The code is very simple:

    CGlobalLog* CGlobalLog::m_instance=NULL;  //static instance
    CGlobalLog::CGlobalLog()
    {
        minimiumLogLevel = LOGLEVEL_INFO;   
    }

    CGlobalLog::~CGlobalLog(void)
    {
        if(m_instance != NULL)
            delete m_instance;
    }

            // this method is static
    CGlobalLog& CGlobalLog::getInstance()
    {

        if(m_instance == NULL){
            m_instance = new CGlobalLog();
        }
        return *m_instance;

    }

Where LOGLEVEL is an enum and m_instance is CGlobalLog* CGlobalLog::m_instance. The trace is:

WARNING: Visual Leak Detector detected memory leaks!
---------- Block 504 at 0x009B2290: 92 bytes ----------
  Call Stack:
    c:\users\ferran\directo\gameprojects2008\zeleste2d\src\log\globallog.cpp (26): LogSystem_v2.exe!glog::CGlobalLog::getInstance + 0x7 bytes
    c:\users\ferran\directo\gameprojects2008\zeleste2d\src\log\globallog.cpp (235): LogSystem_v2.exe!glog::CGlobalLog::exposeAPI
    c:\users\ferran\directo\gameprojects200开发者_Go百科8\games_and_samples\logsystem_v2\src\main.cpp (47): LogSystem_v2.exe!main + 0xB bytes
    f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (586): LogSystem_v2.exe!__tmainCRTStartup + 0x19 bytes
    f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (403): LogSystem_v2.exe!mainCRTStartup
    0x767D339A (File and line number not available): kernel32.dll!BaseThreadInitThunk + 0x12 bytes
    0x774D9ED2 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x63 bytes
    0x774D9EA5 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x36 bytes
  Data:
    00 00 00 00    CD CD CD CD    CD CD CD CD    CD CD CD CD     ........ ........
    CD CD CD CD    28 23 9B 00    00 00 00 00    00 00 00 00     ....(#.. ........
    CD CD CD CD    CD CD CD CD    CD CD CD CD    CD CD CD CD     ........ ........
    B0 23 9B 00    00 00 00 00    01 00 00 00    00 00 00 00     .#...... ........
    CD CD CD CD    00 CD CD CD    CD CD CD CD    CD CD CD CD     ........ ........
    CD CD CD CD    00 00 00 00    0F 00 00 00                    ........ ........

I couldn't find any reason for a mem leak.... could you helpme, please? Thanks in advance


First of all... How do you imagine to destructor get called? Do you call anywhere something that will destroy your object?

Secondly calling delete pointer in destructor will cause call of another destructor of same object. So you have recursive destructor call in here. As it is singleton class your call can be simply replaced with delete this;. You should only set m_instance to NULL, so another call of getInstance will not reference to freed memory.

Solution? write static method "deleteInstance" that will check if m_instance is not null and call delete, on m_instance and set it back to null. Then you should call i.e. at end of main function CGlobalLog::deleteInstance();. This way you will supress this memory leak


Presumably you never actually create a local CGlobalLog because you're always using the pointer returned by GetInstance, so the destructor never gets called. In this case it's a good thing, since you really don't want to delete your static instance until the program is finished. You'll need to make an explicit call to delete the instance member at the end of the program.


I response myself. Shame of me!! Sometimes I only need to explain the problem to find the solution. m_instance is never deleted because destructor is private, so it's a leak.


The constructor CGlobalLog::CGlobalLog() has to initialize m_instance to NULL. Note that if not, the results are undefined (maybe memory loss, or an invalid delete).


There is a race condition in CGlobalLog::getInstance() which could result in CGlobalLog objects being leaked. Imagine two threads A and B call CGlobalLog::getInstance() "at the same time". Thread A checks m_instance, determines that it is not NULL, and then prepares to construct a new CGlobalLog object. But before the call to new begins, the OS switches to Thread B. Thread B checks that m_instance is not NULL, constructs a new CGlobalLog object, and assigns it to m_instance. The OS might then switch to Thread A. Thread A, continuing where it left off, also constructs a new CGlobalLog object and assigns it to m_instance, thus leaking the instance allocated by Thread B.

Another possible cause of the problem is that the CGlobalLog destructor deletes m_instance if it is not NULL. When the object being deleted is the CGlobalLog object pointed to by m_instance, then the object is doubly-deleted.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜