(1.1)#malloc与free之间的协议测试
g由malloc函数分配的堆内存使用free函数释放归属权的时候,在free函数中是不必提供一个参数入口来指明所需释放的字节大小的。这是由于malloc与free这两个对子之间存在着一些协议的规范使得free函数可以依照协议按图索骥,找到需要释放由malloc函数申请的堆内存大小信息。
而这个协议就是,malloc函数在分配堆内存并把一个首地址递交返回时,在首地址的前八个字节的上存储了malloc函数申请堆内存的大小。free函数读取执行时先读取malloc申请返回的首地址的前八字节就能够实现不需要额外从其函数窗口得知内存范围的前提下来处理用户申请堆内存的释放。
测试的方法可以通过申请一段由pfirst指针指向首地址的堆内存,然后再申请下一段由pnext指针指向首地址相邻一段堆内存。下一段堆内存的首地址pnext与pfirst存储的首地址的代数差(递增的堆)就是malloc函数分配在pfitst指向的堆的内存容量V。通过打印pfirst指针指向的前八个字节(记为X)来比对V与X的相关程度就可以验证上述协议是否真确,程序设计的思路就是分别打印出V与X来进行观测:
#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
#define oneByte_length "%hhd "
void Test()
{
uint8_t* pfirst=malloc(20);
uint8_t* pnext=malloc(1);
printf("分配到归属pfirst管理的内存有%lu个\n",((uint64_t)pnext-(uint64_t)pfirst));
//尝试输出pfirst的前8个字节
for(int shift=1;shift<=8;shift++)
{
if(shift==1)
printf("前8个字节逐个输出为:");
printf(oneByte_length,*(pfirst-shift));
}
free(pfirst);
free(pnext);
}
void main()
{
Test();
}
其执行结果为:

可见,V与X相差1,而测试分配其他数值时比如分配malloc等于60时,需要的容量开销V与X也是还是相差了1:

V和X一定是相关的,而至于为什么总是相差1,就现在掌握的信息来说还不得而知。不过可以反向推导利用的时,如果利用pfirst的指向去故意改变X的数值,那么当执行free(pfirst)的时候,必定会出现异常。就像这样利用下面的程序故意地去破环malloc与free的协议:
#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>
#define oneByte_length "%hhd "
void Test()
{
uint8_t* pfirst=malloc(20);
uint8_t* pnext=malloc(1);
*(pnext)=20;
printf("分配到归属pfirst管理的内存有%lu个\n",((uint64_t)pnext-(uint64_t)pfirst));
//尝试输出pfirst的前10个字节
for(int shift=1;shift<=8;shift++)
{
if(shift==8)
*(pfirst-shift)=50;
if(shift==1)
printf("前8个字节逐个输出为:");
printf(oneByte_length,*(pfirst-shift));
}
free(pfirst);
free(pnext);
// printf(oneByte_length,*(pnext));
}
void main()
{
Test();
}
结果是系统检查到报错无疑,
