如何在Linux C++程序中获取重载new运算符的源码调用位置?
解决Linux C++重载new获取调用位置的方案
要在不使用调用栈的前提下获取new运算符的源码调用位置,你可以通过宏替换+重载带位置参数的operator new实现,具体步骤如下:
1. 重载带文件、行号参数的operator new
首先重载支持传入文件路径和行号的operator new(包括普通版本和数组版本),在函数内记录位置信息:
#include <cstdlib> #include <iostream> // 重载普通new,接收文件和行号参数 void* operator new(size_t size, const char* file, int line) { void* ptr = malloc(size); // 这里可以将内存地址、大小、文件、行号存入日志或全局统计结构 std::cout << "Allocated " << size << " bytes at " << file << ":" << line << std::endl; return ptr; } // 对应数组new的重载 void* operator new[](size_t size, const char* file, int line) { return operator new(size, file, line); }
2. 用宏替换默认new
通过预处理器宏,将所有普通new调用自动替换为带位置参数的形式:
#define new new(__FILE__, __LINE__) #define new[] new[](__FILE__, __LINE__)
这样当你写Foo* p = new Foo;时,预处理器会将其替换为Foo* p = new(__FILE__, __LINE__) Foo;,自动调用我们重载的带参数版本,编译期就注入了文件和行号信息,完全没有运行时调用栈的开销。
为什么你之前的默认参数方案失效?
C++标准规定,普通的new T语法只会匹配operator new(size_t)签名的重载。带额外参数的operator new必须通过placement new语法(new(参数) T)才能触发,因此你写的带默认参数的版本不会被普通new调用,自然无法生效。
额外注意事项
- 如果需要支持
delete时关联位置信息,可以考虑在分配内存时将位置信息和内存地址绑定,释放时查询对应记录。 - 若代码中存在显式的placement new调用,需要避免宏替换冲突,可以用
#undef new临时取消宏定义,用完再恢复。
内容的提问来源于stack exchange,提问作者Baruian
相关产品推荐
相关产品推荐

