#define _CLNEW new(__FILE__, __LINE__)记录使用了new的文件名及行号,调试用

//Macro for creating new objects
#if defined(LUCENE_ENABLE_MEMLEAKTRACKING)
#define _CLNEW new(__FILE__, __LINE__)
#define LUCENE_BASE public CL_NS(debug)::LuceneBase
#elif defined(LUCENE_ENABLE_REFCOUNT)
#define _CLNEW new
#define LUCENE_BASE public CL_NS(debug)::LuceneBase
#else
#define _CLNEW new
#define LUCENE_BASE public CL_NS(debug)::LuceneVoidBase
#define LUCENE_BASE_CHECK(obj) (obj)->dummy__see_mem_h_for_details
#endif


============================================
==================一个具体的例子=====================
============================================

#include <iostream>
#define _DEBUG
#ifdef _DEBUG
//#ifndef _DEBUG
#define New new(__FILE__, __LINE__)
void* operator new(size_t size, const char* filename, int lineno)
{
std::cout << "NEW :: filename = " << filename << ", lineno = " << lineno << std::endl;
return operator new(size);
}
#else
#define New new
#endif
int main(int argc, char** argv)
{
int *p = New int;
std::cout << "Hello World!" << std::endl;
delete p;
return 0;
}
前一阵子,偶尔会发生mc/mp crash的情况。从产生的core中分析应该是内存混乱所致。经Eric、Roger等一起讨论研究了有关内存操作方面的知识,在此代为记录,以作今后工作的参考,并欢迎各位同仁指正。

1.memrecorder
[b]期间roger作了称为memrecorder的程序,主要思想是将所有内存操作函数(包括 malloc、realloc、free与new、delete、delete[])用macro替换成对应的自定义函数(如Malloc、 Realloc等)。在实现中要将程序调用以上这些函数的位置(文件名与行号)记录下来,在查出问题时(如delete两次)可找到相关的位置(如此内存 是在哪里new的,上一次delete是在哪里)。由于new操作符可作重载:[/b]
new的原型:
void* operator new(size_t);
可重载为:
Void* operator new(size_t, const char* filename, int lineno);
这样子可以使用macro
#define new New(__FILE__, __LINE__)
就可以将所有new调用的位置(文件名与行号)都记录下来,除delete外的其它函数也可作相同的处理。
以下为重载new操作的例子:
<shell># cat -n test.cpp
1 #include <iostream>
2
3 void* operator new(size_t size, const char* filename, int lineno)
4 {
5 std::cout << "NEW: filename = " << filename << ", lineno = " << lineno << std::endl;
6 return operator new(size);
7 }
8
9 int
10 main(int argc, char** argv)
11 {
12 int *p = new(__FILE__, __LINE__) int;
13 std::cout << "Hello World!" << std::endl;
14 delete p;
15 return 0;
16 }
17
<shell># g++ test.cpp
<shell># ./a.out
NEW: filename = test.cpp, lineno = 12
Hello World!
以下为重载delete操作的例子:
<shell># cat -n test.cpp
1 #include <iostream>
2
3 void operator delete(void* ptr, size_t size, const char* filename, int lineno)
4 {
5 std::cout << "DEL: filename = " << filename << ", lineno = " << lineno << std::endl;
6 operator delete(ptr);
7 }
8
9 int
10 main(int argc, char** argv)
11 {
12 int *p = new int;
13 std::cout << "Hello World!" << std::endl;
14 delete(__FILE__, __LINE__) p;
15 return 0;
16 }
17

<shell># g++ test.cpp
test.cpp: In function `int main(int, char**)':
test.cpp:14: error: type `int' argument given to `delete', expected pointer
test.cpp:14: error: expected `;' before "p"
<shell>#
这样若要记住delete处的位置,则只能通过macro:
#define delete strcpy(filename,__FILE__), line=__LINE__, Delete
由于delete后跟有指针,所以只能使用逗号表达式来连接前面两个赋值语句。

但由此出现了另一个的问题,由于filename与line是全局变量,在delete某类时,若析构基类或析构数据成员时也调用了 delete,则filename与line会被改写,等到真正析构该类时就找不到原来的位置了。为解决它引入了一个堆栈来保存在此delete链中所有 的位置。在Delete函数中其位置从此堆栈中取出。这样较好地解决了以上的问题。
由于pwlib中也有类似的内存检查机制,见pwlib/include/ptlib/object.h:
1024 #define PNEW new (__FILE__, __LINE__)
1025
1026 #if !defined(_MSC_VER) || _MSC_VER<1200
1027 #define PSPECIAL_DELETE_FUNCTION
1028 #else
1029 #define PSPECIAL_DELETE_FUNCTION \
1030 void operator delete(void * ptr, const char *, int) \
1031 { PMemoryHeap::Deallocate(ptr, Class()); } \
1032 void operator delete[](void * ptr, const char *, int) \
1033 { PMemoryHeap::Deallocate(ptr, Class()); }
1034 #endif
1035
1036 #define PNEW_AND_DELETE_FUNCTIONS \
1037 void * operator new(size_t nSize, const char * file, int line) \
1038 { return PMemoryHeap::Allocate(nSize, file, line, Class()); } \
1039 void * operator new(size_t nSize) \
1040 { return PMemoryHeap::Allocate(nSize, NULL, 0, Class()); } \
1041 void operator delete(void * ptr) \
1042 { PMemoryHeap::Deallocate(ptr, Class()); } \
1043 void * operator new[](size_t nSize, const char * file, int line) \
1044 { return PMemoryHeap::Allocate(nSize, file, line, Class()); } \
1045 void * operator new[](size_t nSize) \
1046 { return PMemoryHeap::Allocate(nSize, NULL, 0, Class()); } \
1047 void operator delete[](void * ptr) \
1048 { PMemoryHeap::Deallocate(ptr, Class()); } \
1049 PSPECIAL_DELETE_FUNCTION
1050 。。。 。。。

Src文件也一致,有些文件定义了new的macro,如:
src/ptlib/common/contain.cxx:508:#define new PNEW
src/ptlib/common/sockets.cxx:686:#define new PNEW
src/ptlib/common/collect.cxx:229:#define new PNEW
src/ptlib/common/safecoll.cxx:70:#define new PNEW
而有些就没有,如:
include/ptlib/dict.h
include/ptlib/array.h
这样会导致new宏与PNEW宏的冲突,最后决定在所有pwlib中删除有关PNEW的语句。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值