代码之家  ›  专栏  ›  技术社区  ›  PeterK

在使用我的DLL的应用程序中新建/删除时出现奇怪的问题

  •  4
  • PeterK  · 技术社区  · 14 年前

    对不起,题目有点晦涩。我有一个奇怪的问题,我不知道为什么会发生。幸运的是,所涉及的代码非常简单。但在我们开始之前,让我简单描述一下我的应用程序。它是一个多线程应用程序,提供大量数据。类似于内存数据库。可以在其中包含多个“数据库”,并在运行时加载/卸载它们。现在问题是内存释放。请参阅下面的代码(类名称等已更改,但这不重要):

    void SS::AllocTree( double*** pba, int i, int d, int b, int split )
    {
        this->m_tree = new my_tree( pba, i, d, b, split );
    }
    
    void SS::DeallocTree()
    {
        delete this->m_tree;
        this->m_tree = NULL;
    }
    

    每一次 delete this->m_tree 被调用,程序崩溃。堆栈跟踪如下所示:

         mydll.dll!_free_base(void * pBlock=0x0000000008496f70)  Line 109 + 0x14 bytes  C
        mydll.dll!_free_dbg_nolock(void * pUserData=0x0000000008496fa0, int nBlockUse=0x00000001)  Line 1428    C++
         mydll.dll!_free_dbg(void * pUserData=0x0000000008496fa0, int nBlockUse=0x00000001)  Line 1258 + 0xe bytes  C++
        mydll.dll!operator delete(void * pUserData=0x0000000008496fa0)  Line 54 + 0x12 bytes    C++
        mydll.dll!my_tree::`vector deleting destructor'()  + 0x94 bytes C++
        myprog.exe!SS::DeallocTree()  Line 57 + 0x34 bytes  C++
        myprog.exe!SSUnloader(void * arg=0x00000000084d6f80)  Line 1038 C++
        msvcr90d.dll!_callthreadstart()  Line 295   C
        msvcr90d.dll!_threadstart(void * ptd=0x00000000084dad30)  Line 277  C       
    

    以下是树分配的堆栈跟踪:

         msvcr90d.dll!malloc(unsigned __int64 nSize=0x0000000000000058)  Line 56 + 0x21 bytes   C++
        msvcr90d.dll!operator new(unsigned __int64 size=0x0000000000000058)  Line 59 + 0xa bytes    C++
        myprog.exe!SS::AllocTree(double * * * pba=0x0000000008458ff0, int i=0x00000bde, int d=0x00000010, int b=0x00000008, int split=0x00000001)  Line 52 + 0xa bytes  C++
        myprog.exe!SSLoader(void * arg=0x000000000843cf80)  Line 932    C++
        msvcr90d.dll!_callthreadstart()  Line 295   C
        msvcr90d.dll!_threadstart(void * ptd=0x0000000008440d30)  Line 277  C
    

    如您所见,加载/卸载是由专门为此任务创建的单独线程完成的。没有,我没有使用任何花哨的东西,没有自定义堆或任何东西,没有在我的dll或程序中的自定义运算符new/delete。我不知道为什么程序会进入我的dll并在那里调用delete,但是如果是new,就不会发生这种情况。如果我换了 DeallocTree() 像这样:

    void SS::DeallocTree()
    {
        ::operator delete( this->m_tree );
        this->m_tree = NULL;
    }
    

    然后一切正常。但是,我不确定这是否正确。我要不要为新来的接线员做点类似的事?我怎么能保证这个问题不会在其他地方发生呢?为了完整起见,我还附加了此版本DeallocTree()的堆栈跟踪:

        msvcr90d.dll!operator delete(void * pUserData=0x00000000086f5fa0)  Line 45 + 0xa bytes  C++
        myprog.exe!SS::DeallocTree()  Line 58   C++
        myprog.exe!SSUnloader(void * arg=0x0000000008735f80)  Line 1038 C++
        msvcr90d.dll!_callthreadstart()  Line 295   C
        msvcr90d.dll!_threadstart(void * ptd=0x0000000008739d30)  Line 277  C
    

    有人能给我解释一下这是怎么回事吗?

    编辑:
    澄清:
    动态加载my.dll-VS 2008输出: myprog.exe':已加载“C:* \调试\mydll.dll',已加载符号。
    注意:我正确地将dll的调试版本与程序的调试版本一起使用,反之亦然。
    **我的树声明为:
    我的树

    1 回复  |  直到 14 年前
        1
  •  6
  •   Goz    14 年前

    嗯,线索似乎在调用堆栈中。在“delete”调用堆栈中,您会注意到它直接在mydll.dll中调用各种delete函数等。在分配中,分配由msvcr90d.dll执行。

    您所拥有的是在exe上设置的/MDd(或/MD-in-release)标志和在dll上设置的/MTd(或/MT-in-release)。将它们都设置为/MDd(或/MD-in-release),您的问题就会消失。。。基本上,您将同时设置exe和dll来调用CRT dll,而不是尝试用两种不同的方法来调用它。。。