问题起于一段程序:
for(p=head;p!=NULL;p=p->next)
{
free(p);
}
这里 既然p都被释放了 怎么还能引用p->next呢?
free()函数到底做了什么? [问题点数:30分,结帖人c87527124]
收藏
-
c87527124
-
c87527124
-
等级:
-
结帖率:96.77%
|
楼主
发表于: 2012-07-05 10:15:41
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void
GetMemory(
char
**p,
int
num)
{
*p =
malloc
(num);
}
int
main()
{
char
*str=NULL;
str=(
char
*)
malloc
(100);
if
(str!=NULL) {
printf
(
"%p\n"
, str);
}
free
(str);
if
(str!=NULL) {
printf
(
"%p\n"
, str);
}
return
0;
}
|
我的意思是,free(str)之后,str的值仍然不变,是不是说free()函数释放了str之前指向的内存块,但并不改变str自身的值?
在malloc()之后,被分配的那块内存被记了下来,不再作其它用途;free()之后,系统认为那块内存空闲,可以自由处理?
然后无论malloc()抑或free()都不改变str自身的值,str值有效与否需要程序员自己负责?
我的问题就是这样,各位大神还有什么知道的也欢迎告诉我!
谢谢!
|
|
-
tujiaw
-
tujiaw
-
等级:
|
#2 得分:1
回复于: 2012-07-05 10:37:27
我的意思是,free(str)之后,str的值仍然不变,是不是说free()函数释放了str之前指向的内存块,但并不改变str自身的值?
对的
|
|
-
turingo
-
图灵狗
-
等级:
|
#3 得分:6
回复于: 2012-07-05 10:47:35
1、free只是释放了malloc所申请的内存,并不改变指针的值;
2、由于指针所指向的内存已经被释放,所以其它代码有机会改写其中的内容,相当于该指针从此指向了自己无法控制的地方,也称为野指针;
3、为了避免失误,最好在free之后,将指针指向NULL。
|
|
-
z373375579
-
心死
-
等级:
|
#4 得分:0
回复于: 2012-07-05 10:52:18
printf("%p\n", str);打出的是指针的值,也就是地址吧。肯定不变啊
|
|
-
z373375579
-
心死
-
等级:
|
#5 得分:1
回复于: 2012-07-05 10:55:57
建议用完把指针指向NULL.
|
|
-
zhao4zhong1
-
zhao4zhong1
-
等级:
更多勋章
|
#6 得分:0
回复于: 2012-07-05 11:12:32
将对应的内存块标记为可用(即可被本进程或其它进程申请占用)。
|
|
-
qixing1115
-
qixing1115
-
等级:
|
#7 得分:1
回复于: 2012-07-05 11:50:20
不一定不变,free,malloc后可以使两个空闲空间合并,里面有标识的分配情况记录
|
|
-
WizardOz
-
WizardOz
-
等级:
|
#9 得分:8
回复于: 2012-07-05 13:38:35
内核通过一个红黑树来记录了空闲的内存,malloc就是从树中查找一块大小适合的内存并把地址给你,然后把这个节点从树中摘除,避免被别人分配到产生冲突。这个内存现在归你一个人用了。
free函数是把你的这个内存重新放回到红黑树中,让别人可以申请到这个内存。从逻辑上来说,你现在不能在使用这个内存了,因为它已经不属于你。但是系统的实现上目前没有做到,所以你还是能访问这个地址。
另外,系统也不会帮你覆盖内存中的数据,因为做这一个操作浪费时间,没有必要。
打一个简单的比方。你租了一套房子,后来租期到了,房子回到房东手里,或者又转租给别人。但是你拿着原来的钥匙还是能进入那套房子,虽然这个是不合法的。
|
|
-
pdpfd
-
技术才是王道
-
等级:
|
#10 得分:0
回复于: 2012-07-05 14:52:33
free(str):释放str指针所指的内存...让别人可以再次申请....
malloc()与free()相反....
|
|
-
zhao4zhong1
-
zhao4zhong1
-
等级:
更多勋章
|
#11 得分:1
回复于: 2012-07-05 15:13:23
而且你进入这套房子后,里面不一定就一定有变化。(^_^)
|
|
-
shunzyt
-
shunzyt
-
等级:
|
#12 得分:1
回复于: 2012-07-05 16:43:39
free只是向操作系统交出申请的那块内存的控制权,但是内存里的内容还未来得及改变,也许下一刻就改变了,假如有新的申请内存请求的话,可能操作系统就会把这块内存重新分配出去,也可能把别的内存分配出去
|
|
-
wizard_tiger
-
wizard_tiger
-
等级:
|
#13 得分:1
回复于: 2012-07-06 09:16:48
用free()函数之后,指针所指向的内存区域被释放,这块内存可以被其他程序使用,
在没有被其他程序使用前所存储的数据没有被改变,结果不确定。
|
|
-
wizard_tiger
-
wizard_tiger
-
等级:
|
#14 得分:0
回复于: 2012-07-06 09:17:33
用free()函数之后,指针所指向的内存区域被释放,这块内存可以被其他程序使用,
在没有被其他程序使用前所存储的数据没有被改变,结果不确定。
|
|
-
fengfengdiandia
-
疯疯癫癫
-
等级:
|
#15 得分:0
回复于: 2012-07-06 10:30:49
+1 很形象
|
|
-
c87527124
-
c87527124
-
等级:
|
#16 得分:0
回复于: 2012-07-06 11:11:52
感谢各位亲,但是小菜我还有2个问题:(这次回答的大大太多了,感觉分数严重不够用了。。。表示要多水,多挣积分,下次多给分
1》
7楼的大大 说 “不一定不变,free,malloc后可以使两个空闲空间合并,里面有标识的分配情况记录”,貌似这和大部分亲说的有区别啊,到底怎么回事?各位有没有仔细看到这句话?斟酌一下
2》
free()释放内存的大小是怎么判定的?
释放一块连续的内存需要2个要素:首地址,内存大小;首地址可以根据 free(str)的参数str确定,那内存大小呢?是malloc()时就已经记录下来的?
|
|
-
jiejiejieppp
-
jiejiejieppp
-
等级:
|
#17 得分:0
回复于: 2012-07-06 11:44:34
++
|
|
-
luckyaslan
-
左眼看到鬼
-
等级:
|
#18 得分:0
回复于: 2012-07-06 12:26:42
学习了
|
|
-
flowingfirefly
-
flowingfirefly
-
等级:
|
#19 得分:0
回复于: 2012-07-06 13:50:41
void free(void *ptr) : 解除引用, 释放资源
|
|
-
coldsnow3
-
coldsnow3
-
等级:
|
#20 得分:0
回复于: 2012-07-06 13:56:42
租房子的比喻,太给力了
|
|
-
txzsp
-
txzsp
-
等级:
|
#21 得分:1
回复于: 2012-07-06 14:17:37
free释放了malloc申请的内存,不改变指针的值
|
|
-
jack960330
-
欧阳春晖
-
等级:
|
#22 得分:0
回复于: 2012-07-06 22:19:09
3楼说得对
|
|
-
embed_rookie
-
embed_rookie
-
等级:
|
#23 得分:0
回复于: 2012-07-06 23:08:40
++
|
|
-
wszzfzsc
-
wszzfzsc
-
等级:
|
#24 得分:0
回复于: 2012-07-06 23:15:53
释放内存
|
|
-
a7411053
-
a7411053
-
等级:
|
#25 得分:1
回复于: 2012-07-06 23:23:26
free(str)释放了str指示的内存空间,str这个指针变量本身仍然存在。这就是悬垂指针问题
|
|
-
tomsoft
-
BadCat
-
等级:
|
#26 得分:6
回复于: 2012-07-06 23:34:34
应该确切讲是不变的。内存管理多数是通过一个MBC链表实现的,及你实际分配的内存空间为:(nSize + 3) / 4 * 4 + sizeof(MBC)的大小,在malloc之后,系统程序实际返回的是分配的MBC地址+sizeof(MBC),释放内存时,free所做的第一个动作是ptr - sizeof(MBC)得到实际的MBC块,在这个MBC块中包含了该内存的大小,内存MBC链的指针等信息;所以,如果你使用了超出实际分配内存大小的空间,会造成整个MBC链的混乱,最直接表现是程序在free时在另一个不相关的地方出现了异常;所以您可以看出来,在执行了free之后,该块内存并没有改变,即使该块内存相邻内存为空,而发生了内存块的合并,您刚才使用的内存空间也没有发生改变(你看到的),改变的是MBC链表;
详细的内存管理程序您可以参考一些库,如dlmalloc,这个库除了使用了MBC链外,还是用了沙箱机制;事实上早期DOS的内存管理程序也是使用的MBC链;
|
|
-
tomsoft
-
BadCat
-
等级:
|
#27 得分:0
回复于: 2012-07-06 23:39:23
这是一个正式的内存管理程序free片段
void free(void * lptrBlk)
{
if(lptrBlk == NULL ) return;
MBCHEAD *lptrPreBlk; // 前一个内存块
MBCHEAD *lptrNextBlk; // 后一个内存块
register MBCHEAD *lptrMBCBlk = (MBCHEAD *)Mem2Chunk(lptrBlk);
...
其中:
#define Mem2Chunk(p) ((MBCHEAD *)((U32)p - MBCHeadSize)) // 将一个已使用内存块转换成一个Chunk块;基于效能的原因我
// 没有效验内存指针的合法性
|
|
-
tomsoft
-
BadCat
-
等级:
|
#28 得分:0
回复于: 2012-07-06 23:44:46
我读过DOS的内存管理,也读过Linux下著名的DL内存管理(Linux的2.4的内核我基本通读过),我怎么从来没有听说过什么红黑树的概念?是大学课本上的吗?
|
|
-
Ever_lover
-
Ever_lover
-
等级:
|
#29 得分:0
回复于: 2012-07-07 01:46:42
看看源码不就知道了
|
|
-
liuchao35758600
-
LC-Soft
-
等级:
|
#30 得分:1
回复于: 2012-07-07 08:06:31
不改变指针的值,也不改变指针指向的内存空间里的数据,他改变的,只是该内存空间的属性。
调用malloc函数分配内存的时候,得到的内存是属于你这个程序的。
调用free函数后,这块内存空间就不属于你的程序的了,其它程序都可以调用malloc函数分配内存,有可能得到该块内存,进而修改里面的数据。
|
|
-
liuchao35758600
-
LC-Soft
-
等级:
|
#31 得分:1
回复于: 2012-07-07 08:12:04
就是赵老师说的:
申请的时候就已经记录下来了,不然的话,它也不知道这块内存到底要释放多少。
记得有个地方说free函数不仅仅是释放内存,还会整理内存碎片,合并临近内存空间(大致意思是这样的)。。。
|
|
-
tomsoft
-
BadCat
-
等级:
|
#32 得分:0
回复于: 2012-07-07 12:11:30
关于楼上的以及红黑树,我想应该是理解上的问题:
1)我注意到之上的回复多数是基于系统端的,(如红黑树,我在Understand Linux kernal中还真没有听说过红黑树,最后居然在国内网站找到了 ---- 不知道是不是只是国内学术名词,是内核的内存管理);系统内存分配涉及属性、内存页面以及是否有MCU;但是注意一点malloc和free并不是直接使用系统内存管理程序,在多数Linux程序中malloc和free一般是通过标准库,及我说过的DL内存管理程序实现的;因此,内核的内存管理和我们在应用层面的内存管理(如malloc/free)不要混为一谈;
2)DL的内存管理从效能上要比直接使用系统的内存管理效能要高,如经过我们实测:在随机大小、随机顺序申请释放 ---- 目的在制造最差情况,DL内存管理程序是直接使用系统的3~3.9倍,考虑使用realloc,DL内存管理程序是系统的10~43.35倍;所以,实际情况下,我们并不是直接使用系统内存管理 ---- 只是我们并不知道。
|
|
-
xiying12571
-
xiying12571
-
等级:
|
#33 得分:0
回复于: 2012-07-07 13:45:05
free()是释放的函数
|
|
-
yuweilong000
-
yuweilong000
-
等级:
|
#34 得分:0
回复于: 2013-08-15 17:18:22
学习了 论坛是个好地方
|
|