我有一个64位Visual Studio 2010(单线程)C
Windows应用程序,我试图集成tcmalloc和我在使用任何动态链接的DLL时遇到问题.我将tcmalloc链接为静态库. tcmalloc很有效,直到应用程序开始使用我们的共享dll之一.我将解决方案构建为64位DEBUG应用程序.所有dll都与CRT库的C/C++调试版本(MSVCP100D.dll和MVCR100D.dll)相关联.
下面是失败的代码示例.为所有内存分配调用tcmalloc,但是当调用delete时,应用程序崩溃.这对我来说真的很令人费解,因为当我在主可执行文件中创建一个函数并在那里复制代码时,完全相同的代码工作正常.
如果有人在这种情况下使用tcmalloc有任何经验,我将非常感谢您的反馈.这对我来说是一个谜.这是dll的内存模型问题(不同的堆??)?我不知道.在我看来,他们使用相同的堆.
对不起,如果这篇文章太长了.我试图提供尽可能多的信息.
谢谢.
布鲁斯
更新:作为测试,我将崩溃的共享dll更改为静态库,一切正常,直到应用程序使用不同的dll.因此无论出于何种原因,tcmalloc需要一些额外的步骤来处理共享的dll.我可以使用tcmalloc制作所有dll的静态库以进行内存分析,但知道使用共享还需要做什么才真的很好
dll与tcmalloc.
DLL头文件方法声明:
__declspec(dllexport)static std :: string GetExecutablePath();
//.cpp实现
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; }
~_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:
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:
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 }