关于free()释放内存的问题

hackxq 2008-10-25 04:05:50
我在用malloc()和free()时遇到个问题。申请内存后,将一个结构体的指针指向此内存,
用free()释放后,发现好像并不是将申请的内存全部释放了。
以上是将一个结构体放在申请后的内存时的问题,如果将一个几个连续的单个数据放到申请后的内存中时,再用free()释放,好像就不会有上述问题
请高手指教。谢谢。
具体请看如下代码。


#include <stdio.h>
#include <stdlib.h>

//用free()释放内存后,结构体中"b"的值为什么还会保留?free()不是一次释放连续的内存空间吗?如果说free()后是将此块内存标记为可用,在上的数据依然存在,只是下次malloc()时后覆盖上新的数据,那为什么存放单个数据时,free()后此数据的值会为0?
main(){
typedef struct{
int a;
int b;
}stru;

void *memory_p=malloc(sizeof(int)*2);
stru *stru_p=(stru *)memory_p; //这里我的理解是将stru_p指向的结构放到由malloc()申请的内存上, 也就是说在这块内存上实例化此结构体
stru_p->a=10; //这里我理解的是stru_p->放在了由malloc()申请的内存上
stru_p->b=20;
free(memory_p);
printf("%d\n",*(int *)memory_p); //用free()释放memory_p指向的内存后,这里输出是0;
printf("%d\n",*(int *)(memory_p+4));/*用free()释放memory_p指向的内存后,再用memory_p访问结构体中的“b”。
输出为什么还是20?
*/
printf("%d\n",stru_p->a); //这里输出是0
printf("%d\n",stru_p->b); //这里和用(memory_p+4)进行访问的结果一样,输出的也是20.


/*------------------------------------------*/

//在申请的内存上存放连续的单个char型数时就不会有像存放结构体一样的问题
void *p=malloc(sizeof(char)*4);
char *char_p=(char *)p;
int i;
for(i=0;i<4;i++){
char temp=97;
char_p[i]=(temp+i);
}
free(p);
printf("%d\n",*(char *)(p+1)); //用free()释放p指向的内在时,这里输出是0
for(i=0;i<4;i++){
printf("%d ",*(char_p+i)); //这里循环输出4个0
}
}

...全文
771 15 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
lzp765 2008-10-27
  • 打赏
  • 举报
回复
记得free掉,哈哈
emailtome 2008-10-27
  • 打赏
  • 举报
回复
2 楼是对的

will2046 2008-10-27
  • 打赏
  • 举报
回复
楼主好细心,PF,PF
hackxq 2008-10-27
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 zhangyq73 的回复:]
free(anyone_p)后,anyone_p的值不一定是0,而是一个随机值,要程序员赋值为0才可以。如果不赋值为0,可能导致出现野指针。
[/Quote]
free(anyone_p)后,anyone的值为0好像不是随机的。在GCC下应该就确定的0值。不知道在VC下是怎么样的。

刚发现一个有意思的事情,如果anyone_p是一个指向char的指针。free(anyone_p)后,anyone_p+0到anyone_p+3这四个地址里的值都为0,从anyone_p+4开始的地址指向的值还是原值,所以可能是gcc编译时,free()是把四个字节地址的值改成0,一个指针中的地址值不是刚好是四个字节吗
迷途的书童 2008-10-26
  • 打赏
  • 举报
回复
free(p)只释放 p当前所指的内存块!//p=NULL 再把它指象NULL,防止悬垂指针
要想把b也释放再free(p+1)就行!// p+1=NULL 再把它指象NULL,防止悬垂指针


//至于下一个里数组为什么只释放一个P就所有都地址置零;偶也搞不清楚什么原因!
zhangyq73 2008-10-26
  • 打赏
  • 举报
回复
free(anyone_p)后,anyone_p的值不一定是0,而是一个随机值,要程序员赋值为0才可以。如果不赋值为0,可能导致出现野指针。
hackxq 2008-10-26
  • 打赏
  • 举报
回复
感谢大家的回贴

按照大家所说的。free()只是将malloc()的那段内存重新标记为可用,在其上的值等到下次再使用这段内存时会被覆盖。
还有点不明白的地方
我用的是gcc
struct anyone{
int a;
int b;
}*anyone_p;
free(anyone_p)后,anyone_p的值为0了。不用再手工将p指向“NULL”,这算是编译器自定义行为吧?
所以anyone_p->a的值为0, anyone_p->b的没有被值没有被改变,只是空内存被重肃然标记为可用了

如果我上面所解释的是对的。那如下情况该怎么解释

char *p=(char *)malloc(sizeof(char)*2);
*p='a';*(p+1)='b';
free(p);
按上面说的。p的值是0了,可为什么p+1这个地址上的值也为0了?
如果把这里p指向的类型从"char"类型换成"int"类型,p+1这个地址里的值就还是原来的值。这是什么原因?

请大家指教

yangkunhenry 2008-10-25
  • 打赏
  • 举报
回复
路过学习
wenjunsu 2008-10-25
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 hqin6 的回复:]
呵呵,free,内存释放了,只是在计算机里,标记这段内存可读!
而上面的数据不会丢失!

所以建议free之后,应该把指针赋为NULL,避免二次使用!
[/Quote]

二楼正解!
  • 打赏
  • 举报
回复
free之后要把指针null

不然就会出现传说中的野指针

如果不麻烦的话,适当的注释来说明,防止和你公事的xd郁闷。
LiTuX 2008-10-25
  • 打赏
  • 举报
回复
虽然K&R曾经说过编译器应当支持在释放链表时这样:

while(p){
free(p);
p = p->next;
}

但是,我们仍建议释放内存之后就不要在用任何方式使用它,——除非编译器重新分配给你。

帅得不敢出门 2008-10-25
  • 打赏
  • 举报
回复
加个内存泄露检测 没有泄露就说明都释放了
cattycat 2008-10-25
  • 打赏
  • 举报
回复
free了,标记内存可用,里边的数据可能还在,这是不确定的,如果这部分内存被其他数据占用了,你用指针访问会得到不同的值。赞同2楼的说法,free掉后让指针为NULL。
太乙 2008-10-25
  • 打赏
  • 举报
回复
呵呵,free,内存释放了,只是在计算机里,标记这段内存可读!
而上面的数据不会丢失!

所以建议free之后,应该把指针赋为NULL,避免二次使用!
brookmill 2008-10-25
  • 打赏
  • 举报
回复
这种问题不必深究。
作为程序员,只要记住,一块内存free了之后不要再用,就可以了。
至于那块内存被free了之后发生了一些什么样的故事,就不是我们需要或者应该关心的问题了。
不同的系统,在不同的情况下,可能会有各种不同的处理结果。它可能被占用,可能被覆盖,也可能保持不变。

顺便说一句,malloc的标准用法应该是:
stru *stru_p=(stru *)malloc(sizeof(stru));
而不是
void *memory_p=malloc(sizeof(int)*2);
stru *stru_p=(stru *)memory_p;
不过这句可能多余,可能LZ是为了试验故意这样写的吧。

70,020

社区成员

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

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