首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >有没有人能够在使用共享DLL的Windows 64位应用程序上集成tcmalloc?

有没有人能够在使用共享DLL的Windows 64位应用程序上集成tcmalloc?
EN

Stack Overflow用户
提问于 2013-01-10 01:40:30
回答 2查看 5.2K关注 0票数 5

我有一个64位的Visual Studio2010(单线程) C++ Windows应用程序,我试图将它与tcmalloc集成,但在使用我们的任何动态链接的dll时遇到了问题。我将tcmalloc链接为静态库。在应用程序开始使用我们共享的dll之前,tcmalloc工作得很好。我将该解决方案构建为64位调试应用程序。所有动态链接库与C/C++调试版本的CRT库(MSVCP100D.dll和MVCR100D.dll)的链接。

下面是一个失败的代码示例。所有内存分配都会调用tcmalloc,但是当调用delete时,应用程序就会崩溃。当我在主可执行文件中创建一个函数并将代码复制到那里时,这真的让我感到困惑,因为完全相同的代码可以很好地工作。

如果任何人有在这种情况下使用tcmalloc的经验,我将非常感谢您的反馈。这对我来说是个谜。是不是dll的内存模型问题(不同的堆??)?我不知道。在我看来,它们使用的是同一个堆。

如果这篇文章太长了,很抱歉。我试着给你尽可能多的信息。

谢谢。

布鲁斯

更新:作为测试,我将共享dll更改为静态库,在应用程序使用不同的dll之前,一切工作正常。因此,无论出于什么原因,tcmalloc都需要一些额外的步骤来处理共享dll,我可以使用tcmalloc创建所有用于内存分析的dll静态库,但如果能知道在tcmalloc中使用共享dll还需要做些什么,那就太好了。

DLL头文件方法声明:__declspec(dllexport) static std::string GetExecutablePath();

//.cpp实现

代码语言:javascript
运行
复制
string Parameters::GetExecutablePath()

    string  execPathStr;
    char exeFilePath[ MAX_PATH +1];
    if ( GetModuleFileName( NULL, exeFilePath, MAX_PATH ) )
    {
        //The line of code below is where the app crashes.
        //It calls operator new in crt/src/new.cpp. I verified the call to malloc
        //is forwarded to tcmalloc. 
        *execPathStr = string(exeFilePath);* //creates and deletes a temporary and then crashes

        long dir_pos = execPathStr.rfind( FT_DIR_SLASH ) ;
        execPathStr = execPathStr.substr( 0, dir_pos+1 );
    }

    return execPathStr;

}

临时字符串销毁时调用的方法:

代码语言:javascript
运行
复制
~_String_val()
{   
    // destroy the object
    typename _Alloc::template rebind<_Container_proxy>::other _Alproxy(_Alval);
    this->_Orphan_all();
    _Dest_val(_Alproxy, this->_Myproxy);
    **_Alproxy.deallocate(this->_Myproxy, 1);**
    this->_Myproxy = 0;
}


void deallocate(pointer _Ptr, size_type)
{   
    // deallocate object at _Ptr, ignore size
    **::operator delete(_Ptr);**
}

This is where it crashes. the pHead->nBlockUse is 0. 
crt/dbgdel.cpp:

void operator delete(
        void *pUserData
        )
{
    //code omitted for brevity
    /* verify block type */
    **_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));** //crashes here
}

将tcmalloc重建为共享DLL后,在尝试释放内存时,它现在会在不同的位置崩溃。

afxmem.cpp:

代码语言:javascript
运行
复制
void __cdecl operator delete(void* p)
{
#if !defined(_AFX_NO_DEBUG_CRT) && defined(_DEBUG)
        **_free_dbg(p, _NORMAL_BLOCK);** <-------- this function gets called 
#else
        free(p);
#endif
}

dbgheap.c:

代码语言:javascript
运行
复制
extern "C" _CRTIMP void __cdecl _free_dbg(
        void * pUserData,
        int nBlockUse
        )
{
 _mlock(_HEAP_LOCK);

        __try {
            /* allocate the block
             */
            **_free_dbg_nolock(pUserData, nBlockUse);**
        }
   __finally {
            /* unlock the heap
             */
            _munlock(_HEAP_LOCK);
        }
}



extern "C" void __cdecl _free_dbg_nolock(
        void * pUserData,
        int nBlockUse
        )
{
    //code omitted for brevity

    /*
    * If this ASSERT fails, a bad pointer has been passed in. It may be
    * totally bogus, or it may have been allocated from another heap.
    * The pointer MUST come from the 'local' heap.
    */
    **_ASSERTE(_CrtIsValidHeapPointer(pUserData));** <-------- crashes here
}
EN

回答 2

Stack Overflow用户

发布于 2013-01-17 07:26:10

我们终于让tcmalloc可以在Windows 64位平台上使用共享的dll了。感谢健忘船长的建议!诀窍是在Visual Studio2010中构建一个带有调试符号的发布版本,如本文所述:How to: Debug a Release Build。tcmalloc与MFC中的CRT调试堆调用存在冲突,例如:_free_dbg。我们从tcmalloc分配内存,并从MFC CRT堆调试调用中释放内存。在发布版本中,这个问题就消失了。我们做了一些初步测试,tcmalloc正在生成堆配置文件调用图。

谢谢。

布鲁斯

票数 2
EN

Stack Overflow用户

发布于 2013-01-10 02:33:49

通过静态链接tcmalloc,每个使用tcmalloc的DLL都会获得自己的库内部状态副本(包括堆和所有指针)。如果您通过tcmalloc从一个DLL分配内存,然后尝试从另一个DLL删除内存,则操作将失败,因为您最终访问了多个堆。

将tcmalloc链接为动态库,这样您的问题就会消失。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14243186

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档