メモリリーク使用後のtypeinfo::name()
-
25-10-2019 - |
質問
しているプログラムのもと、情報提供をロギング、出力の名前のクラスをそのまま使用される(具体的には私は追加のエントリのログをとる Messages::CSomeClass transmitted to 127.0.0.1
).これによりコード、例えば次のようなもの:
std::string getMessageName(void) const {
return std::string(typeid(*this).name());
}
あり、誰でもポイントで、この出力 typeinfo::name
は、実装固有のものです。
による MSDN
の
type_info::name
会員機能を返しますconst char*
は、null終了文字列を表す、人間が読める形式の名前タイプです。のメモリを指摘するキャッシュに格納およびすべきではない直接割.
しかし、出口より私のプログラムのデバッガは、"新しい"使用 typeinfo::name()
を示してメモリリークを引き起こします。また出力のための情報2クラス、2つのメモリリーです。このヒントをキャッシュされたデータはないが解放されます。
このような大きな課題で汚し、その後、デバッグセッションで簡単に隠す本メモリはすべて解放されます。
って周囲を見回見つかの有用な情報につい答えにいくらか興味深い情報 どのようtypeinfoに組み込むこともできますがった場合はこのメモリは通常は解放され、システムがあればいい"なお知らせ"の漏えい時のデバッグしやすくなります。
いバックアッププランでは、コードの getMessageName
方法ものではな typeinfo::name
, してしまいましたが、まず私が知った場合には何かがあった。
解決
少し値段が高くなりますが、正しい基礎問題です。これはめったにメモリリーク、虚偽の報告書。のメモリブロックに割り当てtyepinfo()の名前()文字列が割り当て間違ったブロックタイプです。ではないが"無料"このメモリは、以下の試みをされることがありますので必ずCRTフルを設定することができます。良いニュースは、このた固定VS2012(_MSC_VER1700+).
これだけに適用され_DEBUGを以下に示すものがより安全です。この機能_FixTypeInfoBlockUse()を呼び出す必要があ上記で終了する前にモジュールのエントリポイント(メインに、WinMainます。
#if defined(_DEBUG) && (_MSC_VER >= 1000 && _MSC_VER <= 1699)
//
// Debug memory block header:
// o Borrowed from the Microsoft CRT to fix the false "memory leak" report
// when using typeinfo 'name' accessor in a _DEBUG build of the library.
//
struct _CrtMemBlockHeader
{
struct _CrtMemBlockHeader * pBlockHeaderNext;
struct _CrtMemBlockHeader * pBlockHeaderPrev;
char * szFileName;
int nLine;
#ifdef _WIN64
int nBlockUse;
size_t nDataSize;
#else
size_t nDataSize;
int nBlockUse;
#endif
long lRequest;
unsigned char gap[4];
};
static void __cdecl _FixTypeInfoBlockUse(void)
{
__type_info_node* pNode = __type_info_root_node._Next;
while(pNode != NULL)
{
__type_info_node* pNext = pNode->_Next;
(((_CrtMemBlockHeader*)pNode) - 1)->nBlockUse = _CRT_BLOCK;
if (pNode->_MemPtr != NULL)
(((_CrtMemBlockHeader*)pNode->_MemPtr) - 1)->nBlockUse = _CRT_BLOCK;
pNode = pNext;
}
}
#endif//defined(_DEBUG) && (_MSC_VER >= 1000 && _MSC_VER <= 1699)
他のヒント
私は先ずこの問題のようにクリーンの履歴 VLD.これは、 既知の問題, る固定VC11だけます。に存在する以前のバージョンのMSVCを含む2010年.このバグが表示される場合のみご利用のMFC.ご利用の場合MFCとDLLの代わりに静的ライブラリー、メモリリークが存在するがんを検知します。
がグローバルのキャッシュ type_info
名前でクリアされないのからの抜粋 <typeinfo>
):
struct __type_info_node {
void *_MemPtr;
__type_info_node* _Next;
};
extern __type_info_node __type_info_root_node;
その考え方としては、この明確なります。この機能が働くとう:
#include <typeinfo>
void clear_type_info_cache()
{
__type_info_node* & node = __type_info_root_node._Next;
while(node)
{
if (node->_MemPtr)
{
delete node->_MemPtr;
}
__type_info_node* tempNode = node;
node = node->_Next;
delete tempNode;
}
}
電話 clear_type_info_cache()
前に終了します。登録することができま atexit
#include <cstdlib>
int WinMain(...)
{
atexit(&clear_type_info_cache);
...
}
または電話で直前のWinMain
struct dummy_scope_exit
{
typedef void (*Fun)();
dummy_scope_exit(Fun f) : m_f(f) {}
~dummy_scope_exit() { m_f(); }
Fun m_f;
};
int WinMain(...)
{
dummy_scope_exit cleaner = &clear_type_info_cache;
...
}
指摘されているように、クリス-パートンのコメントここにあるの 既知の問題, 少なくともとのバージョンのコンパイラを使用してい-へのアップグレードVC11うに修正し、またグレードアップを図っています。
る削除の出力 typeinfo::name()
作品の一部:
std::string getMessageName(void) const
{
std::string typeStr(typeid(*this).name());
delete (typeid(*this).name());
return typeStr;
}
しかしさらにそのメモリリーク-だいたいに登場することで知られている二つの漏えいた話によるのかもしれる授業の内の名前空間?).使用上記バージョンのコードでは、このた一漏えいります。
他の溶液に表示される作業であるリンクの動のMFC図書館にあるかを使用していMFCな判断したことのないよ静的バージョン。
VS店舗タイプの情報を単独-リンク一覧です。のヘッダーのこのリストにアクセス可能な、"不透明な構造のアクセス名 __type_情報_root_ノード.実際にはSLIST_HEADERます。
Win32APIは、セットの並行処理-安全機能な構造です。固定メモリリークの報告に必要なすべて削除するノードの一覧です。
#include <Windows.h>
#include <typeinfo>
#include <vld.h>
void ClearTypeinfoCache()
{
#ifdef _DEBUG
while (auto entry = InterlockedPopEntrySList(reinterpret_cast<PSLIST_HEADER>(&__type_info_root_node)))
{
free(entry);
}
#endif
}
int main()
{
atexit(ClearTypeinfoCache);
return 0;
}
更新:VLD2.5.1な報告メモリ漏れtype_info::name()にVS2015更新3.