tcmalloc を統合しようとしている 64 ビットの Visual Studio 2010 (シングル スレッド) C++ Windows アプリケーションがあり、動的にリンクされた dll のいずれかを使用すると問題が発生します。tcmalloc をスタティック ライブラリとしてリンクしました。tcmalloc は、アプリケーションが共有 dll の 1 つを使用し始めるまではうまく機能します。ソリューションを 64 ビット DEBUG アプリケーションとして構築しました。CRT ライブラリの C/C++ デバッグ バージョン (MSVCP100D.dll および MVCR100D.dll) とのすべての 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
}