我在 db(db.dll) 模块定义全局的 static 变量,变量类型为自定义的,实现中有申请内存空间,现在在主程序模块(my.exe)的 ~...App() 函数中执行该类的一个函数将申请的内存释放,结果提示内存泄漏 -324541 Byte,如果不进行释放则提示内存泄漏 360 Byte。理论上说全局的static变量应该留系统处理才是啊,这是怎么回事,我应该怎么处理?

解决方案 »

  1.   

    static 变量是如何实现的?
      

  2.   

    static 变量中有几个成员申请了很大的内存,我是在VS.net2003 下调试的,跟踪发现,执行完析构函数~...App() 后马上弹出对话框提示内存泄漏,之后系统才去调用static 变量的析构函数释放内存,也就是说实际上是没有内存泄漏的(我认为),只是VS.net先提示有内存泄漏才去释放内存。
      

  3.   

    把这个STATIC变量的说明帖出来
      

  4.   

    关键是为什么是在提示内存泄漏之后编译器才去调用static变量的析构函数,是否关系到DLL模块的加载等问题
      

  5.   

    问题还没有解决,请大家继续发表见解,为什么编译器会提示内存泄漏为负数(-324541 Byte),真是百思不得其解
      

  6.   

    在你的类的构造函数中有没有申请内存阿?比如在构造函数中new了什么东西?
    静态成员的析构函数因该由系统来调用。
    要看你的代码才知道了。GoAround(GoAround) 说的情况也可能是问题。为什么编译器会提示内存泄漏为负数(-324541 Byte)
    -----------------
    可能是你多释放了吧
      

  7.   

    我在DB工程添加了一个简单的类进行测试,结果还是像上面一样,测试类如下:
    class MemTest
    {
    public:
        MemTest();
        ~MemTest();
        void FreeMemTest();
    private:
        char *m_cTest;
        bool isFree;
    };MemTest::MemTest()
    {
        m_cTest = new char[100];
        isFree = false;
    }MemTest::~MemTest()
    {
        if (!isFree)
        {
            delete MemTest;
            MemTest = NULL;
            isFree = true;
        }
    }void MemTest::FreeMemTest()
    {
        delete MemTest;
        MemTest = NULL;
        isFree = true;
    }跟踪结果:执行完主程序模块my.exe的函数~myApp()后,提示内存泄漏100byte,然后系统才去调用类MemTest的析构函数来释放内存。 若我在~myApp()函数中执行FreeMemTest()函数先把内存给释放了,则提示内存泄漏 -100byte 。所以主要有两个问题不明白:
    1、为什么系统是在提示内存泄漏之后才去调用变量的析构函数?
    2、为什么系统会提示内存泄漏值为负数?本人目前的猜想:会不会是和 dll 加载、卸载的方式、顺序有关。
      

  8.   

    你是通过loadlibrary来加载dll的吗?
    因该会在freelibrary的时候就会调用析构函数的吧
      

  9.   

    new [] 对应 delete []
      

  10.   

    gohappy_1999(碧水蓝天) 不是已经说了问题原因了吗?楼主看看
      

  11.   

    1、为什么系统是在提示内存泄漏之后才去调用变量的析构函数?==========================================================
    你用的内存管理是不是db.dll里面进行的?弹出那个对话框的代码是谁的代码.btw:编译器是编译器, 运行库是运行库,
      

  12.   

    >> gohappy_1999(碧水蓝天): new [] 对应 delete []
    >> jazy() : gohappy_1999(碧水蓝天) 不是已经说了问题原因了吗?楼主看看发贴时打错了,这里没有问题,谢谢!
    ====================================>> xiaonian_3654(你猜猜(我要打光棍,小乔嫁不了)) :>> 你用的内存管理是不是db.dll里面进行的?>> 弹出那个对话框的代码是谁的代码.>> btw:编译器是编译器, 运行库是运行库释放内存的代码是写在static变量类型的析构里面的,后来又给该类添加了另一个成员函数用于在模块my.exe的~myApp()里调用进行内存的释放,通过另一函数导出:DB_API void FreeMemTest();// 声明static MemTest myMemTest;
    void FreeMemTest() // 实现
    {
        myMemTest.FreeMemTest();
    }以上的所有代码,包括类MemTest都属于db.dll
    在可执行程序模块my.exe的~myApp()中执行 FreeMemTest();
    结果提示内存泄漏为负数,之后系统又自动去调用MemTest类的析构函数
    MemTest::~MemTest()
    {
        if (!isFree)
        {
            delete MemTest;
            MemTest = NULL;
            isFree = true;
        }
    }至于“弹出那个对话框的代码是谁的代码. btw:编译器是编译器, 运行库是运行库”,这个没细看。
    ==========================================由于上班开发用的机子全封闭,不能上网,只是回家再回贴,不好意思,各位!
    请继续多多指导!
      

  13.   

    上贴中的static MemTest myMemTest;
    就是db.dll中发生内存泄漏的静态全局变量。
      

  14.   

    >>弹出那个对话框的代码是谁的代码.>>btw:编译器是编译器, 运行库是运行库请问在这方面可能会存在什么问题?
      

  15.   

    lz的根本问题是析构函数写得不正确。
    请用如下代码试一试(注:省去了“isFree”这个多余的成员变量):MemTest::~MemTest()
    {
        if (NULL != m_cTest )
        {
            delete []m_cTest;
            m_cTest = NULL;
        }
    }
      

  16.   

    回楼上的,isFree变量只是用来检测是否已经调用过函数
    void MemTest::FreeMemTest()
    {
        delete MemTest;
        MemTest = NULL;
        isFree = true;
    }
    释放内存了,是则没必要再释放一次。上面的类只是写来测试的,可能很粗糙,不过现在的结果是和析构函数怎么写没有关系,因为系统是在提示内存泄漏之后才去调用析构函数的,而若在提示之前先把申请的内存释放了,则提示内存泄漏为负数。
      

  17.   

    猜测:在DLL中static变量并不能在多个进程间共享。会不会是这个原因?
    需要在DLL中加上#pragma data_seg...标志
      

  18.   

    class MemTest
    {
    public:
        MemTest();
        ~MemTest();
        void FreeMemTest();
    private:
        char *m_cTest;
        bool isFree;
    };MemTest::MemTest()
    {
        m_cTest = new char[100];
        isFree = false;
    }MemTest::~MemTest()
    {
      FreeMemTest();
    }void MemTest::FreeMemTest()
    {
      if(!isFree)
      {
        delete[] m_cTest;
        m_cTest = NULL;
        isFree = true;
      }
    }
    要是这样还出问题,就继续顶
      

  19.   

    MemTest::~MemTest()
    {
        long lSize = sizeof( MemTest );
        if ( lSize > sizeof(char) )
        {
            delete MemTest;
            MemTest = NULL;
            isFree = true;
        }
    }
    这样应该能避免吧?
      

  20.   

    new 以后只要记得 delete 就不会泄漏
      

  21.   

    谢谢各位的热心,但其实跟析构函数怎么写是没有关系的,因为经过跟踪发现,系统是在提示内存泄漏之后才去调用该析构函数的。以下是MSDN上一位叫“xyb”的网友给的见解,现贴出来大家一起研究一下。
    ========================================================
    让.exe和.dll模块都选用C/C++运行时库的静态库版本试试。我做过下面实验,假定Test1.dll和Test2.dll被连接到同一个C/C++运行时库的DLL版(如MSVCRTD.dll),那么这两个模块将共享同一个运行时库及CRT堆,则这其中的一个模块被卸载时,MFC将把该模块的CRT堆中的所有尚未被释放的内存信息输出到output窗口中,由于另一模块共享了该CRT堆,那么,另一模块中的尚未被释放的内存信息也将作为内存泄漏信息一起被输出。这样输出的内存泄露信息就是错误的。
      

  22.   

    我记得, Charles Petzold, 或者 Jeffery Richter 说过,在 DLL 中申请内存,一定要在 DLL 中释放,否则会泄露...
      

  23.   

    解决方案,在 DLL 中加入释放内存的代码void WINAPI ReleaseAllocatedMemory(void)
    {
        VirtualFree(lpData, 0, MEM_RELEASE);
    }然后在程序中调用ReleaseAllocatedMemory();
      

  24.   

    这个是说,如果你在 DLL 中申请了内存,一定要在 DLL 中释放。在 EXE 中释放是不行的。
      

  25.   

    你的DLL是WIN32 的还是MFC扩展的啊,如果是WIN32 的用在MFC里是会出现这个问题的,因为MFC DEBUG模式下会重定义new操作符,所以这个时候检测到的内存泄露是不准确的。以前ACE讨论过这个问题,你可以找找看。或者编一个MFC扩展DLL试试看。
      

  26.   

    DLL是WIN32的,请问ACE讨论过的这个问题的题目关键字是什么?
      

  27.   

    MemTest::~MemTest()
    {
        long lSize = sizeof( MemTest );
        if ( lSize > sizeof(char) )
        {
            delete MemTest;
            MemTest = NULL;
            isFree = true;
        }
    }
    这样应该能避免吧?
    ---------------------------------------------------------------------
    这样写有道理吗?
    sizeof( MemTest ) 的值应该是不会随着运行阶段的变化而变化吧?我没有写过什么C++
    的程序,但我想,sizeof应该是在编译阶段就已经执行了的。
    还有,在析构函数里面写删除自己的代码,那删除语句之后的语句岂不成了混乱的没有地
    方存放的东西了吗?(我没有用过什么C++,我写过一个脚本解释器,我想,如果要为上面
    这种代码构筑一个运行环境是艰难的,因为,一个对象已经被删除了,但还需要继续运行
    一点该对象的东西,这,有可能吗?)
    小弟对C++了解甚少,如有错误之处,望诸位大师指教。