从内存的角度看free(p) , p=NULL
来源:互联网 发布:域名纠纷 律师 编辑:程序博客网 时间:2024/05/17 09:38
讲C的书多告诉我们malloc出的内存用完要free掉,为了避免出现野指针,还要将指针置为NULL。
今天做了个小实验,从内存的角度看free()究竟做了什么、为什么最后要把指针设为NULL。
-----
看下面的例子:
#include <stdio.h>int main(int argc, char **argv) {int *p = (int *)malloc(sizeof(int));*p = 1;printf("p: %p, *p:%d\n", p, *p); // p: 0x1f1c010, *p:1free(p); // free之后,p的内存地址没有变,而p指向的内容置为0了,此时p是野指针printf("p: %p, *p:%d\n", p, *p); // p: 0x1f1c010, *p:0*p = 2; //错误的操作野指针,观察内存:printf("p: %p, *p:%d\n", p, *p); // p: 0x1f1c010, *p:2// double free错误,这个是肯定的。//free(p);//printf("p: %d, *p:%d\n", p, *p);p = NULL; // 此时不能对p进行解引,p是空指针printf("p: %p\n", p); // p: (nil)return 0;}
---
update:
重新翻了下K&R,发现书上说的也确实如此!
下面是stackoverflow上的一个回答(地址:http://stackoverflow.com/questions/2468853/freeing-memory-twice)
Freeing memory does not set the pointer to null. The pointer remains pointing to the memory it used to own, but which has now had ownership transferred back to the heap manager.
The heap manager may have since reallocated the memory your stale pointer is pointing to.
Freeing it again is not the same as saying free(NULL), and will result in undefined behavior.
我的理解:
在第一次free()调用后,堆管理器将我们free()的内存和相邻的块重新组成了新的更大的块,以便下次malloc()调用,这时,这块内存已经不属于malloc出的内存了,对非malloc出的内存进行free,其结果是未定义的(我们这里是double free crash)。
--
update:
参考:http://code.woboq.org/userspace/glibc/malloc/malloc.c.html
malloc出来的内存块结构:
1. An allocated chunk looks like this:
chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of previous chunk, if allocated | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of chunk, in bytes |M|P|
mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| User data starts here... .
. .
. (malloc_usable_size() bytes) .
. |
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of chunk |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
空闲块结构:
2. Free chunks are stored in circular doubly-linked lists, and look like this:
chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Size of previous chunk |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
`head:' | Size of chunk, in bytes |P|
mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Forward pointer to next chunk in list |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Back pointer to previous chunk in list |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Unused space (may be 0 bytes long) .
. .
. |
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
`foot:' | Size of chunk, in bytes |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
第一次free:
第二次free:
看double free后出现了2块同样的chunk,堆管理器显然是不能同意的!
----
另附blackHat上一篇关于double free()漏洞利用的paper:
https://www.blackhat.com/presentations/bh-usa-07/Ferguson/Presentation/bh-usa-07-ferguson.pdf
- 从内存的角度看free(p) , p=NULL
- 从内存的角度看free(p) , p=NULL
- int *p = NULL; free(p);这样也可以
- char *p = NULL,int *p = NULL的区别
- c/c++中delete/free 指针后,设置p=NULL的好处
- c/c++中delete/free 指针后,设置p=NULL的好处
- c/c++中delete/free 指针后,设置p=NULL的好处
- 【C语言】delete free后设p=NULL的好处
- 为什么delete p;后最好加上p = NULL; ? (浅谈内存泄露和内存过度释放)
- 函数的入口校验时,assert(NULL!=p)与if(NULL!=p)的区别
- 关于 int *p = NULL; char *p = NULL; 的问题:
- int *p=NULL与*p=NULL
- *p=NULL与p=NULL见解
- if(NULL != p)和if( p!=NULL )
- 从内存角度看问题
- int *p=0 与 int *p=NULL 的区别?
- 写一函数free,将上题用new函数占用的空间释放。Free(p)表示将p指向的单元以后的内存段释放
- p,&p,*p的区别
- Linux下Pig的安装和配置
- 重载技巧+简单实现string和Vector
- Python:闭包的理解
- OpenFire 安装文档
- Android应用的Tab键,来回反复点击会报ANR,是空指针导致的,判空就可以解决
- 从内存的角度看free(p) , p=NULL
- 致、我心爱的姑娘
- MooseFS分布式文件系统的注意事项和排错经验
- UITextField和UITextView输入限制解决方案
- 总结一下到新公司后这半个月的工作吧(中)
- PeekMessage&GetMessage
- Python 列表(Lists)
- 20140902写在新一轮学习开始之前的话
- 一般应用程序ashx文件简单实例