关于free函数

来源:互联网 发布:杭州小知科技有限公司 编辑:程序博客网 时间:2024/06/05 18:02

问题起于一段程序:

for(p=head;p!=NULL;p=p->next)

{

free(p);

}


这里 既然p都被释放了  怎么还能引用p->next呢?



CSDN > CSDN论坛 > C/C++ > C语言
  • 管理菜单
  • 结帖
  • 发帖
  • 回复

free()函数到底做了什么? [问题点数:30分,结帖人c87527124]

 收藏
楼主发表于: 2012-07-05 10:15:41
C/C++ code
?
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值有效与否需要程序员自己负责?
我的问题就是这样,各位大神还有什么知道的也欢迎告诉我!
谢谢!
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
回复次数:34
#1 得分:0回复于: 2012-07-05 10:22:55
顶一下自己帖,跪求各位大神解答,谢谢喽
申请Linux免费迁移,拿大奖
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#2 得分:1回复于: 2012-07-05 10:37:27
我的意思是,free(str)之后,str的值仍然不变,是不是说free()函数释放了str之前指向的内存块,但并不改变str自身的值?
对的
关注CSDN论坛微博 送CSDN积分大礼包
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#3 得分:6回复于: 2012-07-05 10:47:35
1、free只是释放了malloc所申请的内存,并不改变指针的值;
2、由于指针所指向的内存已经被释放,所以其它代码有机会改写其中的内容,相当于该指针从此指向了自己无法控制的地方,也称为野指针;
3、为了避免失误,最好在free之后,将指针指向NULL。
软件开发者编程大赛万元大奖等你拿
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#4 得分:0回复于: 2012-07-05 10:52:18
 printf("%p\n", str);打出的是指针的值,也就是地址吧。肯定不变啊
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#5 得分:1回复于: 2012-07-05 10:55:57
建议用完把指针指向NULL.
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#6 得分:0回复于: 2012-07-05 11:12:32
将对应的内存块标记为可用(即可被本进程或其它进程申请占用)。
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#7 得分:1回复于: 2012-07-05 11:50:20
引用 2 楼  的回复:
我的意思是,free(str)之后,str的值仍然不变,是不是说free()函数释放了str之前指向的内存块,但并不改变str自身的值?
对的
不一定不变,free,malloc后可以使两个空闲空间合并,里面有标识的分配情况记录
引用 6 楼  的回复:
将对应的内存块标记为可用(即可被本进程或其它进程申请占用)。
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#8 得分:0回复于: 2012-07-05 13:25:34
地址是地址,内存是内存,指针存地址。
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#9 得分:8回复于: 2012-07-05 13:38:35
内核通过一个红黑树来记录了空闲的内存,malloc就是从树中查找一块大小适合的内存并把地址给你,然后把这个节点从树中摘除,避免被别人分配到产生冲突。这个内存现在归你一个人用了。
free函数是把你的这个内存重新放回到红黑树中,让别人可以申请到这个内存。从逻辑上来说,你现在不能在使用这个内存了,因为它已经不属于你。但是系统的实现上目前没有做到,所以你还是能访问这个地址。
另外,系统也不会帮你覆盖内存中的数据,因为做这一个操作浪费时间,没有必要。

打一个简单的比方。你租了一套房子,后来租期到了,房子回到房东手里,或者又转租给别人。但是你拿着原来的钥匙还是能进入那套房子,虽然这个是不合法的。
对我有用[2] 丢个板砖[0] 引用 | 举报 | 管理
#10 得分:0回复于: 2012-07-05 14:52:33
free(str):释放str指针所指的内存...让别人可以再次申请....
malloc()与free()相反....
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#11 得分:1回复于: 2012-07-05 15:13:23
引用 9 楼  的回复:
内核通过一个红黑树来记录了空闲的内存,malloc就是从树中查找一块大小适合的内存并把地址给你,然后把这个节点从树中摘除,避免被别人分配到产生冲突。这个内存现在归你一个人用了。
free函数是把你的这个内存重新放回到红黑树中,让别人可以申请到这个内存。从逻辑上来说,你现在不能在使用这个内存了,因为它已经不属于你。但是系统的实现上目前没有做到,所以你还是能访问这个地址。
另外,系统也不会帮你覆盖……
而且你进入这套房子后,里面不一定就一定有变化。(^_^)
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#12 得分:1回复于: 2012-07-05 16:43:39
free只是向操作系统交出申请的那块内存的控制权,但是内存里的内容还未来得及改变,也许下一刻就改变了,假如有新的申请内存请求的话,可能操作系统就会把这块内存重新分配出去,也可能把别的内存分配出去
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#13 得分:1回复于: 2012-07-06 09:16:48
用free()函数之后,指针所指向的内存区域被释放,这块内存可以被其他程序使用,
在没有被其他程序使用前所存储的数据没有被改变,结果不确定。
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#14 得分:0回复于: 2012-07-06 09:17:33
用free()函数之后,指针所指向的内存区域被释放,这块内存可以被其他程序使用,
在没有被其他程序使用前所存储的数据没有被改变,结果不确定。
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#15 得分:0回复于: 2012-07-06 10:30:49
+1 很形象
引用 9 楼  的回复:
内核通过一个红黑树来记录了空闲的内存,malloc就是从树中查找一块大小适合的内存并把地址给你,然后把这个节点从树中摘除,避免被别人分配到产生冲突。这个内存现在归你一个人用了。
free函数是把你的这个内存重新放回到红黑树中,让别人可以申请到这个内存。从逻辑上来说,你现在不能在使用这个内存了,因为它已经不属于你。但是系统的实现上目前没有做到,所以你还是能访问这个地址。
另外,系统也不会帮你覆盖……
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#16 得分:0回复于: 2012-07-06 11:11:52
感谢各位亲,但是小菜我还有2个问题:(这次回答的大大太多了,感觉分数严重不够用了。。。表示要多水,多挣积分,下次多给分
1》
7楼的大大 说 “不一定不变,free,malloc后可以使两个空闲空间合并,里面有标识的分配情况记录”,貌似这和大部分亲说的有区别啊,到底怎么回事?各位有没有仔细看到这句话?斟酌一下

2》
free()释放内存的大小是怎么判定的?
释放一块连续的内存需要2个要素:首地址,内存大小;首地址可以根据 free(str)的参数str确定,那内存大小呢?是malloc()时就已经记录下来的?
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#17 得分:0回复于: 2012-07-06 11:44:34
引用 3 楼  的回复:
1、free只是释放了malloc所申请的内存,并不改变指针的值;
2、由于指针所指向的内存已经被释放,所以其它代码有机会改写其中的内容,相当于该指针从此指向了自己无法控制的地方,也称为野指针;
3、为了避免失误,最好在free之后,将指针指向NULL。
++
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#18 得分:0回复于: 2012-07-06 12:26:42
引用 9 楼  的回复:
内核通过一个红黑树来记录了空闲的内存,malloc就是从树中查找一块大小适合的内存并把地址给你,然后把这个节点从树中摘除,避免被别人分配到产生冲突。这个内存现在归你一个人用了。
free函数是把你的这个内存重新放回到红黑树中,让别人可以申请到这个内存。从逻辑上来说,你现在不能在使用这个内存了,因为它已经不属于你。但是系统的实现上目前没有做到,所以你还是能访问这个地址。
另外,系统也不会帮你覆……
学习了
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#19 得分:0回复于: 2012-07-06 13:50:41
void free(void *ptr) : 解除引用, 释放资源
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#20 得分:0回复于: 2012-07-06 13:56:42
引用 9 楼  的回复:
内核通过一个红黑树来记录了空闲的内存,malloc就是从树中查找一块大小适合的内存并把地址给你,然后把这个节点从树中摘除,避免被别人分配到产生冲突。这个内存现在归你一个人用了。
free函数是把你的这个内存重新放回到红黑树中,让别人可以申请到这个内存。从逻辑上来说,你现在不能在使用这个内存了,因为它已经不属于你。但是系统的实现上目前没有做到,所以你还是能访问这个地址。
另外,系统也不会帮你覆盖……

租房子的比喻,太给力了
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#21 得分:1回复于: 2012-07-06 14:17:37
free释放了malloc申请的内存,不改变指针的值
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#22 得分:0回复于: 2012-07-06 22:19:09
引用 3 楼  的回复:
1、free只是释放了malloc所申请的内存,并不改变指针的值;
2、由于指针所指向的内存已经被释放,所以其它代码有机会改写其中的内容,相当于该指针从此指向了自己无法控制的地方,也称为野指针;
3、为了避免失误,最好在free之后,将指针指向NULL。
3楼说得对
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#23 得分:0回复于: 2012-07-06 23:08:40
引用 3 楼  的回复:
1、free只是释放了malloc所申请的内存,并不改变指针的值;
2、由于指针所指向的内存已经被释放,所以其它代码有机会改写其中的内容,相当于该指针从此指向了自己无法控制的地方,也称为野指针;
3、为了避免失误,最好在free之后,将指针指向NULL。
++
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#24 得分:0回复于: 2012-07-06 23:15:53
释放内存
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#25 得分:1回复于: 2012-07-06 23:23:26
free(str)释放了str指示的内存空间,str这个指针变量本身仍然存在。这就是悬垂指针问题
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#26 得分:6回复于: 2012-07-06 23:34:34
引用 16 楼  的回复:
感谢各位亲,但是小菜我还有2个问题:(这次回答的大大太多了,感觉分数严重不够用了。。。表示要多水,多挣积分,下次多给分
1》
7楼的大大 说 “不一定不变,free,malloc后可以使两个空闲空间合并,里面有标识的分配情况记录”,貌似这和大部分亲说的有区别啊,到底怎么回事?各位有没有仔细看到这句话?斟酌一下

2》
free()释放内存的大小是怎么判定的?
释放一块连续的内存需要2……
应该确切讲是不变的。内存管理多数是通过一个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链;
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#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块;基于效能的原因我
                                                            // 没有效验内存指针的合法性


对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#28 得分:0回复于: 2012-07-06 23:44:46
引用 9 楼  的回复:
内核通过一个红黑树来记录了空闲的内存,malloc就是从树中查找一块大小适合的内存并把地址给你,然后把这个节点从树中摘除,避免被别人分配到产生冲突。这个内存现在归你一个人用了。
free函数是把你的这个内存重新放回到红黑树中,让别人可以申请到这个内存。从逻辑上来说,你现在不能在使用这个内存了,因为它已经不属于你。但是系统的实现上目前没有做到,所以你还是能访问这个地址。
另外,系统也不会帮你覆……
我读过DOS的内存管理,也读过Linux下著名的DL内存管理(Linux的2.4的内核我基本通读过),我怎么从来没有听说过什么红黑树的概念?是大学课本上的吗?
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#29 得分:0回复于: 2012-07-07 01:46:42
看看源码不就知道了
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#30 得分:1回复于: 2012-07-07 08:06:31
引用楼主  的回复:
C/C++ code
#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(st……
不改变指针的值,也不改变指针指向的内存空间里的数据,他改变的,只是该内存空间的属性。
调用malloc函数分配内存的时候,得到的内存是属于你这个程序的。
调用free函数后,这块内存空间就不属于你的程序的了,其它程序都可以调用malloc函数分配内存,有可能得到该块内存,进而修改里面的数据。
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#31 得分:1回复于: 2012-07-07 08:12:04
引用 30 楼  的回复:
不改变指针的值,也不改变指针指向的内存空间里的数据,他改变的,只是该内存空间的属性。
调用malloc函数分配内存的时候,得到的内存是属于你这个程序的。
调用free函数后,这块内存空间就不属于你的程序的了,其它程序都可以调用malloc函数分配内存,有可能得到该块内存,进而修改里面的数据。

就是赵老师说的:
引用 6 楼  的回复:
将对应的内存块标记为可用(即可被本进程或其它进程申请占用)。

引用 16 楼  的回复:
free()释放内存的大小是怎么判定的?
释放一块连续的内存需要2个要素:首地址,内存大小;首地址可以根据 free(str)的参数str确定,那内存大小呢?是malloc()时就已经记录下来的?
申请的时候就已经记录下来了,不然的话,它也不知道这块内存到底要释放多少。


记得有个地方说free函数不仅仅是释放内存,还会整理内存碎片,合并临近内存空间(大致意思是这样的)。。。
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#32 得分:0回复于: 2012-07-07 12:11:30
引用 30 楼  的回复:
引用楼主  的回复:
C/C++ code
#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)……
关于楼上的以及红黑树,我想应该是理解上的问题:
1)我注意到之上的回复多数是基于系统端的,(如红黑树,我在Understand Linux kernal中还真没有听说过红黑树,最后居然在国内网站找到了 ---- 不知道是不是只是国内学术名词,是内核的内存管理);系统内存分配涉及属性、内存页面以及是否有MCU;但是注意一点malloc和free并不是直接使用系统内存管理程序,在多数Linux程序中malloc和free一般是通过标准库,及我说过的DL内存管理程序实现的;因此,内核的内存管理和我们在应用层面的内存管理(如malloc/free)不要混为一谈;
2)DL的内存管理从效能上要比直接使用系统的内存管理效能要高,如经过我们实测:在随机大小、随机顺序申请释放 ---- 目的在制造最差情况,DL内存管理程序是直接使用系统的3~3.9倍,考虑使用realloc,DL内存管理程序是系统的10~43.35倍;所以,实际情况下,我们并不是直接使用系统内存管理 ---- 只是我们并不知道。
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#33 得分:0回复于: 2012-07-07 13:45:05
free()是释放的函数
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
#34 得分:0回复于: 2013-08-15 17:18:22
学习了  论坛是个好地方
对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
  • 管理菜单
  • 结帖
  • 发帖
  • 回复
  • 台湾程序员游戏开发经历
  • 陈勇- 敏捷开发现状及发展之路
  • 分享你的发现 赢下载积分

关注CSDN论坛微博送可用分

CSDN论坛微博主要发布程序员职场经验,生活指南,IT八卦等内容,关注就有积分相送噢!

回复内容
  • 编辑
  • 预览
  • 粗体
  • 斜体
  • 下划线
  • ---------------
  • 字体大小
  • 字体颜色
  • ---------------
  • 图片
  • ---------------
  • 左对齐
  • 居中对齐
  • 右对齐
  • ---------------
  • 引用
  • 代码
  • ---------------
  • QQ
  • monkey
  • onion
  • ---------------
  • 押宝
  • ---------------
  • 清除格式
每天回帖即可获得10分可用分!小技巧:教您如何更快获得可用分 你还可以输入10000个字符(Ctrl+Enter)
  1. 这里发言,表示您接受了CSDN论坛的用户行为准则。
  2. 请对您的言行负责,并遵守中华人民共和国有关法律法规,尊重网上道德。
  3. 转载文章请注明出自“CSDN(www.csdn.net)”。如是商业用途请联系原作者。
公司简介|招贤纳士|广告服务|银行汇款帐号|联系方式|版权声明|法律顾问|问题报告
QQ客服 微博客服 论坛反馈 联系邮箱:webmaster@csdn.net 服务热线:400-600-2320
京 ICP 证 070598 号
北京创新乐知信息技术有限公司 版权所有
世纪乐知(北京)网络技术有限公司 提供技术支持
江苏乐知网络技术有限公司 提供商务支持
Copyright © 1999-2012, CSDN.NET, All Rights Reserved GongshangLogo