father *pF = new son;
delete pF;
class A *pA = new class[5];
delete pA;
一般有两种方式: 1 非入侵式,内存分配器自行先申请内存(和栈配合使用),用作记录用户层的申请记录(地址,大小)。 用户释放空间时会查找该表,除了知道释放空间大小外还能判断该指针是合法。 2 入侵式,例如用户要申请1byte的内存,而内存分配器会分配5byte的空间(32位),前面4byte用于申请的大小。释放内存时会先向前偏移4个byte找到申请大小,再进行释放。 两种方法各有优缺点,第一种安全,但慢。第二种快但对程序员的指针控制能力要求更高,稍有不慎越界了会对空间信息做成破坏。我们Linux上的gcc/g++编译器默认使用入侵式,为了验证我们找到的地址是否存储了我们想要的数据,我写了这样的测试代码:
#include
using namespace std;
#if(defined(_X86_) && !defined(__x86_64))
#define _ALLOCA_S_MARKER_SIZE 4
#elif defined(__ia64__) || defined(__x86_64)
#define _ALLOCA_S_MARKER_SIZE 8
#endif
int main(void)
{
void * p = NULL;
int a = 5, n = 1;
while (a--)
{
p = new char[n];
size_t w = *((size_t*)((char*)p - _ALLOCA_S_MARKER_SIZE));
cout<<"w = "<< w <<" n = "<10;
}
return 0;
}
#include
using namespace std;
#include
#include
#include
#if(defined(_X86_) && !defined(__x86_64))
#define _ALLOCA_S_MARKER_SIZE 4
#elif defined(__ia64__) || defined(__x86_64)
#define _ALLOCA_S_MARKER_SIZE 8
#endif
int main(void)
{
void * p = NULL;
srand(time(0));
int a = 100000;
while (a--)
{
int n = rand() % 10000;
p = new char[n];
size_t w = *((size_t*)((char*)p - _ALLOCA_S_MARKER_SIZE));
if ( n <= 8) n = 9;
int n2 = ((n+7) & 0xFFFFFFF0) + 0x11;
assert(n2 == w);
}
return 0;
}
#include
using namespace std;
#include
#include
#if(defined(_X86_) && !defined(__x86_64))
#define _ALLOCA_S_MARKER_SIZE 4
#elif defined(__ia64__) || defined(__x86_64)
#define _ALLOCA_S_MARKER_SIZE 8
#endif
size_t count = 0;
extern "C"
{
void* __real_malloc(int c);
void * __wrap_malloc(int size)
{
void *p = __real_malloc(size);
size_t w = *((size_t*)((char*)p - _ALLOCA_S_MARKER_SIZE)) - 1;
count += w;
cout<<"malloc "<return p;
}
void __real_free(void *ptr);
void __wrap_free(void *ptr)
{
size_t w = *((size_t*)((char*)ptr - _ALLOCA_S_MARKER_SIZE)) - 1;
count -= w;
cout<<"free "<void *operator new(size_t size)
{
return malloc(size);
}
void operator delete(void *ptr)
{
free(ptr);
}
int main(void)
{
count = 0;
int *p1 = new int(3);
int *p2 = new int(4);
cout <<*p1<<' '<<*p2<delete p1;
if(count != 0)
cout<<"memory leak!"<return 0;
}
class father
{
int *p1;
public:
father(){p1 = new int;}
~father(){delete p1;}
};
class son : public father
{
int *p2;
public:
son(){p2 = new int;}
~son(){delete p2;}
};
int main(void)
{
count = 0;
father *p = new son;
delete p;
if(count != 0)
cout<<"memory leak!"<return 0;
}
class A
{
int *p1;
public:
A(){p1 = new int;}
~A(){delete p1;}
};
int main(void)
{
count = 0;
A *p = new A[5];
delete p;
if(count != 0)
cout<<"memory leak!"<return 0;
}
__wrap_malloc
和__wrap_free
链接到一起的文件都起作用,不管是.o、.a或者.so
- 准确性: