-------------------------------------------------------------------
| |实际地址|
-------------------------------------------------------------------
^ ^
| |
p name
它可以用来定义一个变长的结构体,比如你可以动态分配这个结构体,并把分配的长度等于sizeof(struct) + len,这样len这么长的内存就可以直接用最后的那个没有实际空间的指针来引用了。
以上摘自:http://blog.chinaunix.net/u/16231/showart_116414.html
有人提到这样用malloc函数开辟空间后malloc(sizeof(struct) + len)。再用free释放时会不会出问题?
找到的资料来看,都认为不会:
(1)如果你有一个malloc到的指针,可以看一下它所指的地址,在前面一点有一个指明分配的空间的大小的数字,这个就是所谓的“释放内存大小的量”,如果你不相信的话可以用vc试试,我的确看到过。
但是这个数字一般来说不是你malloc或者realloc时候传递的size参数,因为堆分配策略中分配的堆内存不能过于零散,所以一般实际分配的长度是某些特定的值:4B,12B,24B,36B……等等。
楼主可以自己再验证一下,关于嵌入式系统,应该比普通的系统更加严格。
(2)free释放空间 的大小存放在什么地方是由堆的实现决定的.
如sandrowjw所说,如果堆是采用的buddy算法,其释放大小由内存起始地址决定了
如果是其它策略,则这个值可能会存放在指针前的几个字节,也可能存在某个固定的内存区域(只能被堆的实现所访问).
(3)free只传一个指针,是怎么知道要释放的内存大小的呢,有学习过操作系统内存管理的人可能知道,我们申请一块内存的时候,(以下可能不同系统实现不一样):
申请成功,那么系统给我们是一个指针的地址,这个地址里面的某个地方存放着内存块的描述符(包括内存类型和大小)这样,free的时候系统会先读取这个描述符,返回再释放,所以能释放掉所有我们申请的内存,具体详细的还是的学习学习操作系统原理。
当我们得到一个指针的时候,我们可以对其类型做强制转换,这都不影响内存里面的实际空间大小,释放的时候系统还是能安全释放。
可是如果我们对指针地址做了修改,比如:
char *p = (char *)malloc(sizeof(char) * LEN);
int *i = (int *)p;
那么free(i),OK,没问题;
如果
i = (int *)p + 1;
free(i); 那么挂了,呵呵!
就是这样了,地址被你改变了,找不到内存块的描述符了,也就不知道内存的类型和大小,自然也就挂了!
不过这个存放描述符的地址每个系统都不一样(也有可能有一样的,^_^),里面的具体内容也不一样;
评论