试图了解内存泄漏

时间:2011-09-14 22:49:53

标签: c++

我正在使用VLD(Visual Leak Detector),它会检测到一些内存泄漏。我试图理解为什么这是VLD的内存泄漏。这可能是假阳性?

代码非常简单:

    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;

    }

其中LOGLEVEL是枚举,m_instance是CGlobalLog* CGlobalLog::m_instance。 跟踪是:

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\gameprojects2008\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                    ........ ........

我找不到内存泄漏的任何理由......你能帮忙吗? 提前致谢

5 个答案:

答案 0 :(得分:2)

大概你从未真正创建本地CGlobalLog因为你总是使用GetInstance返回的指针,所以析构函数永远不会被调用。在这种情况下,这是一件好事,因为在程序完成之前,您真的不想删除静态实例。您需要显式调用以删除程序末尾的实例成员。

答案 1 :(得分:2)

首先......你怎么想象析构函数被调用?你是否在任何会破坏你的物体的地方打电话?

其次,在析构函数中调用delete指针将导致调用同一对象的另一个析构函数。所以你在这里有递归析构函数调用。由于它是单身类,您的电话可以简单地替换为delete this;。您应该只将m_instance设置为NULL,因此另一个getInstance调用将不会引用释放的内存。

解决方案?编写静态方法“deleteInstance”,它将检查m_instance是否为null并在m_instance上调用delete,并将其设置为null。然后你应该在主函数CGlobalLog::deleteInstance();结束时调用。这样你就会压制这个内存泄漏

答案 2 :(得分:1)

我回应自己。惭愧我!!有时我只需要解释问题就可以找到解决方案。永远不会删除m_instance,因为析构函数是私有的,所以它是一个泄漏。

答案 3 :(得分:1)

构造函数CGlobalLog::CGlobalLog()必须将m_instance初始化为NULL。请注意,如果没有,结果是未定义的(可能是内存丢失,或者是无效的delete)。

答案 4 :(得分:0)

CGlobalLog::getInstance()中存在竞争条件,可能导致CGlobalLog个对象泄露。想象一下,两个线程A和B同时调用CGlobalLog::getInstance()“。线程A检查m_instance,确定它不是NULL,然后准备构造一个新的CGlobalLog对象。但在调用new之前,操作系统切换到线程B.线程B检查m_instance不是NULL,构造一个新的CGlobalLog对象,并将其分配给m_instance。然后,操作系统可能会切换到线程A.线程A继续停止,它​​还构造一个新的CGlobalLog对象并将其分配给m_instance,从而泄漏线程B分配的实例。

问题的另一个可能原因是,如果CGlobalLog析构函数不是m_instance,则NULL析构函数会删除CGlobalLog。当被删除的对象 m_instance指向的{{1}}对象时,该对象被双重删除。