参考:
malloc内存分配字节对齐问题
http://blog.csdn.net/shemangui/article/details/50459102
1.关于分配内存操作的测试:
-> alloc memsize:10485760 allocTime:4025,freeTime:43816
-> alloc memsize:10485760 allocTime:21248,freeTime:1049
-> alloc memsize:10485760 allocTime:3243,freeTime:950
-> alloc memsize:10485760 allocTime:3237,freeTime:831
-> alloc memsize:10485760 allocTime:3138,freeTime:1288
-> alloc memsize:10485760 allocTime:3262,freeTime:848
-> alloc memsize:10485760 allocTime:3378,freeTime:1061
-> alloc memsize:10485760 allocTime:3274,freeTime:1146
-> alloc memsize:10485760 allocTime:1524,freeTime:585
-> alloc memsize:10485760 allocTime:3480,freeTime:1088
--------
-> alloc memsize:10485760 allocTime:3649,freeTime:2814
-> alloc memsize:10486784 allocTime:21639,freeTime:968
-> alloc memsize:10488832 allocTime:1581,freeTime:570
-> alloc memsize:10491904 allocTime:11294,freeTime:1006
-> alloc memsize:10496000 allocTime:12464,freeTime:1158
-> alloc memsize:10501120 allocTime:11743,freeTime:1077
-> alloc memsize:10507264 allocTime:11691,freeTime:1381
-> alloc memsize:10514432 allocTime:5474,freeTime:408
-> alloc memsize:10522624 allocTime:11282,freeTime:899
-> alloc memsize:10531840 allocTime:10269,freeTime:946
不使用free
-> alloc memsize:10485760 allocTime:3594,freeTime:33
-> alloc memsize:10485760 allocTime:22147,freeTime:35
-> alloc memsize:10485760 allocTime:19764,freeTime:92
-> alloc memsize:10485760 allocTime:24867,freeTime:108
-> alloc memsize:10485760 allocTime:24288,freeTime:130
-> alloc memsize:10485760 allocTime:25619,freeTime:122
-> alloc memsize:10485760 allocTime:10792,freeTime:44
-> alloc memsize:10485760 allocTime:22506,freeTime:141
-> alloc memsize:10485760 allocTime:22518,freeTime:108
-> alloc memsize:10486784 allocTime:23219,freeTime:94
-> alloc memsize:10488832 allocTime:22277,freeTime:171
-> alloc memsize:10491904 allocTime:25335,freeTime:135
-> alloc memsize:10496000 allocTime:16881,freeTime:63
-> alloc memsize:10501120 allocTime:27219,freeTime:136
-> alloc memsize:10507264 allocTime:20322,freeTime:90
-> alloc memsize:10514432 allocTime:23304,freeTime:95
-> alloc memsize:10522624 allocTime:22770,freeTime:151
-> alloc memsize:10531840 allocTime:23454,freeTime:91
测试结论:
1.malloc在首次申请内存时较快(这是不是因为程序启动前就Break指针就指在一个合适的MappingArea?),
第二次分配会变慢(初次Break指的范围的MappingArea不够用了,需要扩展Mapping,耗时?)
如果前面调用free过一次相近的内存块,那么在此malloc内存块时,就会变得快一点,大概加速了5-10倍;
这验证了malloc内部有内存块缓存功能,并没有还回给OS,malloc内部维护这一个空闲列表进行内存分配的加速处理。
2.关于释放操作的测试:
malloc内存分配字节对齐问题
http://blog.csdn.net/shemangui/article/details/50459102
1.关于分配内存操作的测试:
int getNTick()
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC,&ts);
int ns = ts.tv_sec * 1000*1000000 + ts.tv_nsec;
return ns;
}
void test(int mem_size)
{
int t1=getNTick();
char* buf = new char[mem_size];
//memset(buf,0,mem_size);
int t2=getNTick();
int use1=t2-t1;
//memset(buf,1,mem_size);
//free(buf);
//memset(buf,2,mem_size);
//free(buf);
int use2=getNTick()-t2;
printf("-> alloc memsize:%d allocTime:%d,freeTime:%d\n",mem_size,use1,use2);
}
使用free
-> alloc memsize:10485760 allocTime:4025,freeTime:43816
-> alloc memsize:10485760 allocTime:21248,freeTime:1049
-> alloc memsize:10485760 allocTime:3243,freeTime:950
-> alloc memsize:10485760 allocTime:3237,freeTime:831
-> alloc memsize:10485760 allocTime:3138,freeTime:1288
-> alloc memsize:10485760 allocTime:3262,freeTime:848
-> alloc memsize:10485760 allocTime:3378,freeTime:1061
-> alloc memsize:10485760 allocTime:3274,freeTime:1146
-> alloc memsize:10485760 allocTime:1524,freeTime:585
-> alloc memsize:10485760 allocTime:3480,freeTime:1088
--------
-> alloc memsize:10485760 allocTime:3649,freeTime:2814
-> alloc memsize:10486784 allocTime:21639,freeTime:968
-> alloc memsize:10488832 allocTime:1581,freeTime:570
-> alloc memsize:10491904 allocTime:11294,freeTime:1006
-> alloc memsize:10496000 allocTime:12464,freeTime:1158
-> alloc memsize:10501120 allocTime:11743,freeTime:1077
-> alloc memsize:10507264 allocTime:11691,freeTime:1381
-> alloc memsize:10514432 allocTime:5474,freeTime:408
-> alloc memsize:10522624 allocTime:11282,freeTime:899
-> alloc memsize:10531840 allocTime:10269,freeTime:946
不使用free
-> alloc memsize:10485760 allocTime:3594,freeTime:33
-> alloc memsize:10485760 allocTime:22147,freeTime:35
-> alloc memsize:10485760 allocTime:19764,freeTime:92
-> alloc memsize:10485760 allocTime:24867,freeTime:108
-> alloc memsize:10485760 allocTime:24288,freeTime:130
-> alloc memsize:10485760 allocTime:25619,freeTime:122
-> alloc memsize:10485760 allocTime:10792,freeTime:44
-> alloc memsize:10485760 allocTime:22506,freeTime:141
-> alloc memsize:10485760 allocTime:22518,freeTime:108
-> alloc memsize:10485760 allocTime:23545,freeTime:121
-------
-> alloc memsize:10485760 allocTime:3675,freeTime:42-> alloc memsize:10486784 allocTime:23219,freeTime:94
-> alloc memsize:10488832 allocTime:22277,freeTime:171
-> alloc memsize:10491904 allocTime:25335,freeTime:135
-> alloc memsize:10496000 allocTime:16881,freeTime:63
-> alloc memsize:10501120 allocTime:27219,freeTime:136
-> alloc memsize:10507264 allocTime:20322,freeTime:90
-> alloc memsize:10514432 allocTime:23304,freeTime:95
-> alloc memsize:10522624 allocTime:22770,freeTime:151
-> alloc memsize:10531840 allocTime:23454,freeTime:91
测试结论:
1.malloc在首次申请内存时较快(这是不是因为程序启动前就Break指针就指在一个合适的MappingArea?),
第二次分配会变慢(初次Break指的范围的MappingArea不够用了,需要扩展Mapping,耗时?)
如果前面调用free过一次相近的内存块,那么在此malloc内存块时,就会变得快一点,大概加速了5-10倍;
这验证了malloc内部有内存块缓存功能,并没有还回给OS,malloc内部维护这一个空闲列表进行内存分配的加速处理。
2.关于释放操作的测试:
指令序列:
char* buf = (char*) malloc(mem_size);
free(buf);
free(buf);
操作结果:程序并没有崩溃;
---------------------------------
char* buf = new char[mem_size]
free(buf);
free(buf);
操作结果:double free or corruption 导致崩溃;
-----------------------------------
char* buf = (char*) malloc(mem_size);
delete(buf);
delete(buf);
操作结果:double free or corruption 导致崩溃;
测试推论:
1.new操作,在malloc的基础上,应该增加了一些状态判断字段,使得释放内存操作时,会主动查看这些标志来判断是否是重复释放,以abort进程的方式防御非法指令;
2.这验证了new一定与delete匹配,malloc与free匹配,不要交叉使用,虽然有时候并没有问题产生。
3.其实把buf 执行free之后,buf还是可以照常使用,没问题;但是不建议做,这会引发相同内存块被其他线程分配得到,而产生不可预测的风险。
3.关于Heap内存的一次分配的,上界,下界,地址分配规律,地址对齐问题的测试:
void test2()
{
char* buf=new char[1024];
for(int i;i<5000;i++)
{
buf[i]=0;
printf("%d %p\n",i,&buf[i]);
}
/*
Program received signal SIGABRT, Aborted.
Assertion `(old_top == initial_top (av) && old_size == 0) ||
((unsigned long) (old_size) >= MINSIZE && prev_inuse (old_top) &&
((unsigned long) old_end & (pagesize - 1)) == 0)' failed.
*/
}
void test3()
{
char* buf1=(char*)malloc(1024);
char* buf2=(char*)malloc(1024);
char* buf3=(char*)malloc(1024);
char* buf4=(char*)malloc(1024);
printf("buf1:%p\n",buf1);
printf("buf2:%p\n",buf2);
printf("buf3:%p\n",buf3);
printf("buf4:%p\n",buf4);
free(buf4);
char* buf5=(char*)malloc(1024);
printf("buf5:%p\n",buf5);
//结果
//buf1:0x1f70c20
//buf2:0x1f71030
//buf3:0x1f71440
//buf4:0x1f71850
//buf5:0x1867850 与buf4一样,说明了free只是把block缓存到空闲列表,供下次需要直接取出;
//buf1、buf2相距1040字节,并不是相距1024字节
}
void test4()
{
srand(time(NULL)+ getNTick()%123243555 );
int n=rand()%102232287;
char* buf=(char*)malloc(n);
void* p = buf;
long p2 = (long)p;
float f = float(p2)/float(16);
printf("%d %p %f\n",n,buf,f);
//验证分配的地址以16字节对齐
}
void test2()
{
void* p1=sbrk(0);
char* buf=new char[1024];
printf("buf:%p\n",buf);
void* p2= sbrk(0);
printf("brk:%p brk2:%p\n",p1,p2);
char* buf2 = new char[1024*127];
printf("brk3:%p buf2: %p\n", sbrk(0),buf2);
char* buf4 = new char[1024*180];
printf("brk4:%p buf4: %p\n", sbrk(0),buf4);
/*
buf:0x2125c20
brk:0x2146000 brk2:0x2146000
brk3:0x2167000 buf2: 0x2126440
brk4:0x2167000 buf4: 0x7f8ebf271010
推论:程序一启动编译器就把Break指针指向0x2146000,计算0x2146000-0x2125c20=132064即为进程预备了大约128K的Heap空间<可以测试
出可用的heap大约是200K>;
如果剩余找不到一个内存size满足预分配的内存,break指针就偏移4096字节进行扩展;
如果某次要分配的内存的大约200K以上,那么进行使用mmap得到大内存块;可以发现0x7f8ebf271010明显区别于前面的地址形式;
brk:0x2146000与4096对齐;
*/
}
void test4()
{
printf("test4\n");
long stack=0x00007FFFFFFFFFFF;
long s=0x2125c20;
void* p = sbrk(0);
char* p2 = (char*)p;
printf("111\n");
long* pz = (long*)(p2-1024*32);
printf("222\n");
*pz=1;
pz=(long*)s;
*pz=2;
/*
程序启动就会一段预先mapping好的内存块,大约200K;如果指定指针操作一块不在mapping范围的地址,或者非userspace区域的地址,就会出现段错误;
*/
}
4.总结:引起Coredump错误的原因如下:
1.尝试写数据到一块没有mapping好的地址,或者非userspace的地址、因此产生段错误;
举例说明:强制操作一块不确定地址的内存;使用未初始化的内存;写NULL指针;循环操作或者buf+offset被偏移到了一个非mapping的地址等;
2.因为程序的断言条件不被满足,而主动abort产生的崩溃,使得进程被终止;比如重复free,divzero,stackoverflow等;