free()函数到底做了什么?

c87527124 2012-07-05 10:15:41
#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值有效与否需要程序员自己负责?
我的问题就是这样,各位大神还有什么知道的也欢迎告诉我!
谢谢!
...全文
8068 37 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
37 条回复
切换为时间正序
请发表友善的回复…
发表回复
TouTouch 2014-09-09
  • 打赏
  • 举报
回复
牛掰,又学到了一点东西
笑尘一梦 2014-05-06
  • 打赏
  • 举报
回复
底层的东西,牛掰
Sleepwalker2013 2013-08-15
  • 打赏
  • 举报
回复
学习了 论坛是个好地方
「已注销」 2012-07-07
  • 打赏
  • 举报
回复
[Quote=引用 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)……
[/Quote]
关于楼上的以及红黑树,我想应该是理解上的问题:
1)我注意到之上的回复多数是基于系统端的,(如红黑树,我在Understand Linux kernal中还真没有听说过红黑树,最后居然在国内网站找到了 ---- 不知道是不是只是国内学术名词,是内核的内存管理);系统内存分配涉及属性、内存页面以及是否有MCU;但是注意一点malloc和free并不是直接使用系统内存管理程序,在多数Linux程序中malloc和free一般是通过标准库,及我说过的DL内存管理程序实现的;因此,内核的内存管理和我们在应用层面的内存管理(如malloc/free)不要混为一谈;
2)DL的内存管理从效能上要比直接使用系统的内存管理效能要高,如经过我们实测:在随机大小、随机顺序申请释放 ---- 目的在制造最差情况,DL内存管理程序是直接使用系统的3~3.9倍,考虑使用realloc,DL内存管理程序是系统的10~43.35倍;所以,实际情况下,我们并不是直接使用系统内存管理 ---- 只是我们并不知道。
灼眼的超哥 2012-07-07
  • 打赏
  • 举报
回复
[Quote=引用 30 楼 的回复:]
不改变指针的值,也不改变指针指向的内存空间里的数据,他改变的,只是该内存空间的属性。
调用malloc函数分配内存的时候,得到的内存是属于你这个程序的。
调用free函数后,这块内存空间就不属于你的程序的了,其它程序都可以调用malloc函数分配内存,有可能得到该块内存,进而修改里面的数据。
[/Quote]

就是赵老师说的:
[Quote=引用 6 楼 的回复:]

将对应的内存块标记为可用(即可被本进程或其它进程申请占用)。
[/Quote]

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


记得有个地方说free函数不仅仅是释放内存,还会整理内存碎片,合并临近内存空间(大致意思是这样的)。。。
灼眼的超哥 2012-07-07
  • 打赏
  • 举报
回复
[Quote=引用楼主 的回复:]
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……
[/Quote]
不改变指针的值,也不改变指针指向的内存空间里的数据,他改变的,只是该内存空间的属性。
调用malloc函数分配内存的时候,得到的内存是属于你这个程序的。
调用free函数后,这块内存空间就不属于你的程序的了,其它程序都可以调用malloc函数分配内存,有可能得到该块内存,进而修改里面的数据。
Ever_lover 2012-07-07
  • 打赏
  • 举报
回复
看看源码不就知道了
xiying12571 2012-07-07
  • 打赏
  • 举报
回复
free()是释放的函数
左眼看到鬼 2012-07-06
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 的回复:]

内核通过一个红黑树来记录了空闲的内存,malloc就是从树中查找一块大小适合的内存并把地址给你,然后把这个节点从树中摘除,避免被别人分配到产生冲突。这个内存现在归你一个人用了。
free函数是把你的这个内存重新放回到红黑树中,让别人可以申请到这个内存。从逻辑上来说,你现在不能在使用这个内存了,因为它已经不属于你。但是系统的实现上目前没有做到,所以你还是能访问这个地址。
另外,系统也不会帮你覆……
[/Quote]
学习了
「已注销」 2012-07-06
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 的回复:]

内核通过一个红黑树来记录了空闲的内存,malloc就是从树中查找一块大小适合的内存并把地址给你,然后把这个节点从树中摘除,避免被别人分配到产生冲突。这个内存现在归你一个人用了。
free函数是把你的这个内存重新放回到红黑树中,让别人可以申请到这个内存。从逻辑上来说,你现在不能在使用这个内存了,因为它已经不属于你。但是系统的实现上目前没有做到,所以你还是能访问这个地址。
另外,系统也不会帮你覆……
[/Quote]
我读过DOS的内存管理,也读过Linux下著名的DL内存管理(Linux的2.4的内核我基本通读过),我怎么从来没有听说过什么红黑树的概念?是大学课本上的吗?
jiejiejieppp 2012-07-06
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]

1、free只是释放了malloc所申请的内存,并不改变指针的值;
2、由于指针所指向的内存已经被释放,所以其它代码有机会改写其中的内容,相当于该指针从此指向了自己无法控制的地方,也称为野指针;
3、为了避免失误,最好在free之后,将指针指向NULL。
[/Quote]
++
「已注销」 2012-07-06
  • 打赏
  • 举报
回复
这是一个正式的内存管理程序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块;基于效能的原因我
// 没有效验内存指针的合法性


「已注销」 2012-07-06
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 的回复:]

感谢各位亲,但是小菜我还有2个问题:(这次回答的大大太多了,感觉分数严重不够用了。。。表示要多水,多挣积分,下次多给分
1》
7楼的大大 说 “不一定不变,free,malloc后可以使两个空闲空间合并,里面有标识的分配情况记录”,貌似这和大部分亲说的有区别啊,到底怎么回事?各位有没有仔细看到这句话?斟酌一下

2》
free()释放内存的大小是怎么判定的?
释放一块连续的内存需要2……
[/Quote]
应该确切讲是不变的。内存管理多数是通过一个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链;
a7411053 2012-07-06
  • 打赏
  • 举报
回复
free(str)释放了str指示的内存空间,str这个指针变量本身仍然存在。这就是悬垂指针问题
wszzfzsc 2012-07-06
  • 打赏
  • 举报
回复
释放内存
c87527124 2012-07-06
  • 打赏
  • 举报
回复
感谢各位亲,但是小菜我还有2个问题:(这次回答的大大太多了,感觉分数严重不够用了。。。表示要多水,多挣积分,下次多给分
1》
7楼的大大 说 “不一定不变,free,malloc后可以使两个空闲空间合并,里面有标识的分配情况记录”,貌似这和大部分亲说的有区别啊,到底怎么回事?各位有没有仔细看到这句话?斟酌一下

2》
free()释放内存的大小是怎么判定的?
释放一块连续的内存需要2个要素:首地址,内存大小;首地址可以根据 free(str)的参数str确定,那内存大小呢?是malloc()时就已经记录下来的?
embed_rookie 2012-07-06
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]

1、free只是释放了malloc所申请的内存,并不改变指针的值;
2、由于指针所指向的内存已经被释放,所以其它代码有机会改写其中的内容,相当于该指针从此指向了自己无法控制的地方,也称为野指针;
3、为了避免失误,最好在free之后,将指针指向NULL。
[/Quote]
++
疯疯癫癫 2012-07-06
  • 打赏
  • 举报
回复
+1 很形象
[Quote=引用 9 楼 的回复:]
内核通过一个红黑树来记录了空闲的内存,malloc就是从树中查找一块大小适合的内存并把地址给你,然后把这个节点从树中摘除,避免被别人分配到产生冲突。这个内存现在归你一个人用了。
free函数是把你的这个内存重新放回到红黑树中,让别人可以申请到这个内存。从逻辑上来说,你现在不能在使用这个内存了,因为它已经不属于你。但是系统的实现上目前没有做到,所以你还是能访问这个地址。
另外,系统也不会帮你覆盖……
[/Quote]
欧阳春晖 2012-07-06
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]

1、free只是释放了malloc所申请的内存,并不改变指针的值;
2、由于指针所指向的内存已经被释放,所以其它代码有机会改写其中的内容,相当于该指针从此指向了自己无法控制的地方,也称为野指针;
3、为了避免失误,最好在free之后,将指针指向NULL。
[/Quote]
3楼说得对
wizard_tiger 2012-07-06
  • 打赏
  • 举报
回复
用free()函数之后,指针所指向的内存区域被释放,这块内存可以被其他程序使用,
在没有被其他程序使用前所存储的数据没有被改变,结果不确定。
加载更多回复(16)

70,024

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧