【发布时间】:2014-09-20 13:45:04
【问题描述】:
我使用宏代替new 在调试模式下获取一些额外信息:
#if defined(_DEBUG)
#define SAGE_NEW new(__FUNCTION__, __FILE__, __LINE__)
#else
#define SAGE_NEW new
#endif
我发现这在自定义内存分析和内存泄漏检测中非常有用。我刚开始使用共享指针,所以现在我正在制作堆对象,例如:
auto myThingy = std::shared_ptr<Thingy>(SAGE_NEW Thingy(Args) );
我刚刚了解到std::make_shared 是首选,因为它使用较少的内存分配。有什么办法可以将我的SAGE_NEW 包含在make_shared 中?我意识到泄漏检测并不重要,但我仍然希望它用于内存使用统计。似乎allocate_shared 以某种方式掌握了答案,但我还没有弄清楚。谢谢! :)
编辑:
对于那些询问new 的人-我用自定义new 重载它。编译器选项 SAGE_MEM_INFO 打开泄漏检测和内存使用统计信息,否则它会跳过日志记录并直接进入我的内存池分配。我有 new[] 和 delete[] 变体,但为简洁起见,我省略了它们:
#ifdef SAGE_MEM_INFO
void* operator new (size_t size){ ++appAllocs; return myAlloc(size); }
void* operator new (size_t size, char const *function, char const *filename, int lineNum)
{
... Log memory usage
void* ptr = ::operator new(size);
return ptr;
}
void operator delete (void* ptr)
{
... Log freeing of this pointer
--appAllocs;
myFree(ptr);
}
void operator delete (void* ptr, char const *function, char const *filename, int lineNum)
{
... Log freeing of this pointer
--appAllocs;
myFree(ptr);
}
#else
void* operator new (size_t size){ return myAlloc(size); }
void* operator new (size_t size, char const *function, char const *filename, int lineNum)
{
void* ptr = ::operator new(size);
return ptr;
}
void operator delete (void* ptr) { myFree(ptr); }
void operator delete (void* ptr, char const *function, char const *filename, int lineNum) { myFree(ptr); }
#endif
【问题讨论】:
-
快速评论:人们经常提到 make_shared 的内存分配。这是真的,但这是一次性成本(每个指针)。另一个很好的理由是,当您使用 make_shared 时,对象本身及其引用计数(可能还有其他内容)都被放入一个连续的内存块中。这会为复制和删除副本带来更好的缓存行为,每个创建的指针可能会重复多次。
-
如果您有解决方案,请将其写为答案。问题框是为,嗯,你的问题。
-
对于您的原始宏,如上所示,您需要记住定义一个相应的放置
operator delete,因为如果构造函数抛出,则放置新表达式会调用它。没有它,您会遇到内存泄漏,这是您要消除的东西。这曾经是一个臭名昭著的 MFC 错误。 -
我从未见过像
new(__FUNCTION__, __FILE__, __LINE__)这样的语法。你能给我指出发生了什么的参考吗? cplusplus.com/reference/new/operator%20new 没有提到为调试做类似的事情。你在接受额外参数的地方有一个重载的 operator new 吗?
标签: c++ c++11 make-shared