ica*_*bod 8 c++ memory-leaks typeid typeinfo visual-c++
我有一个程序,其中,部分用于信息日志记录,我输出一些类的名称,因为它们被使用(特别是我在日志中添加一个条目说明Messages::CSomeClass transmitted to 127.0.0.1
).我使用类似于以下代码执行此操作:
std::string getMessageName(void) const {
return std::string(typeid(*this).name());
}
Run Code Online (Sandbox Code Playgroud)
是的,在任何人指出它之前,我意识到输出typeinfo::name
是特定于实现的.
根据MSDN
所述
type_info::name
成员函数返回一个const char*
到表示该类型的人类可读名称的空终止字符串.指向的内存是缓存的,永远不应该直接释放.
但是,当我在调试器中退出程序时,任何"新"使用都会typeinfo::name()
显示为内存泄漏.如果我输出2个类的信息,我会得到2个内存泄漏,依此类推.这暗示缓存的数据永远不会被释放.
虽然这不是一个主要问题,但它看起来很混乱,经过长时间的调试后,它可以很容易地隐藏真正的内存泄漏.
我环顾四周,发现了一些有用的信息(一个SO答案给出了一些有关如何实现typeinfo的有趣信息),但我想知道这个内存是否应该被系统释放,或者我是否可以做些什么来解决调试时"不注意"泄漏.
我确实有一个备份计划,即getMessageName
自己编写方法并不依赖typeinfo::name
,但无论如何我想知道是否有我错过的东西.
小智 4
另一种解决方案是纠正根本问题。这并不是真正的内存泄漏,只是一个错误的报告。分配给 typeinfo() 和 name() 字符串的内存块被分配了错误的块类型。“释放”该内存可能不是一个好主意,因为 CRT 将尝试再次释放它。好消息是这个问题最终在 VS2012 (_MSC_VER 1700+) 中得到修复。
由于这仅适用于 _DEBUG 构建,因此以下可能是更安全的解决方案。函数 _FixTypeInfoBlockUse() 应在退出模块入口点(main、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)
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1878 次 |
最近记录: |