鱼C论坛

 找回密码
 立即注册
查看: 4856|回复: 11

一个关于malloc函数的问题,新手求解答

[复制链接]
发表于 2012-11-4 00:15:54 | 显示全部楼层 |阅读模式
10鱼币
先上代码
  1. # include <stdio.h>
  2. # include <malloc.h> void f(int * pArr, int i);
  3. void g(int * pArr, int i); int main(void)
  4. {
  5. int i;
  6. printf("请输入你要定义的数组大小:\n");
  7. scanf("%d", &i);
  8. int * p = (int *)malloc(sizeof(int) * i); free(p); f(p, i);
  9. g(p, i); free(p); //在定义动态变量的时候,一定不要忘了释放内存// f(p, i);
  10. // g(p, i); return 0;
  11. }void f(int * pArr, int i)
  12. {
  13. printf("请输入数组每个数的值!\n");
  14. int j;
  15. for (j=0; j<i; ++j)
  16.   scanf("%d", &pArr[j]);
  17. printf("输入完毕!!\n");}void g(int * pArr, int i)
  18. {// printf("%d\n", pArr[i-2]); int j = 0;  /*
  19.      要是检查没有语法错误,就检查标点符号吧,
  20.      尤其是逗号和分号,还要注意是在英文状态下输入的
  21.      */
  22. for (j=0; j<i; ++j) //
  23.   printf("%d  ", pArr[j]);}

复制代码
在台式机上的在g();函数运行完之后就出
file:///C:/Users/Administrator/AppData/Roaming/Tencent/Users/312024054/QQ/WinTemp/RichOle/ZH1QSTTJ0TEJO6O]8OUK2OE.jpg
但在笔记本上的时候free();函数起不到释放内存的作用,就算吧free()后面的两个函数的注释去点仍能正常运行,不会出现内存的问题

求解答,说明一下,我是用的VC++6.0,

第一次发帖提问,勿喷,如果有什么没交代清楚的可以回贴问,但现在要睡觉了,等明天起来回答

最佳答案

查看完整内容

我已经对你的代码整理了一下,并加上了一些解释,如果有其他问题,请回复提问 补充内容 (2012-11-4 01:19): int *p = (int *)malloc(sizeof(int) * i); free(p); 不是说申请了不能马上释放,这是绝对没问题的 问题就只有2个: 1.释放了的空间再次使用 2.对同一块空间释放2次
小甲鱼最新课程 -> https://ilovefishc.com
发表于 2012-11-4 00:15:55 | 显示全部楼层

我已经对你的代码整理了一下,并加上了一些解释,如果有其他问题,请回复提问

  1. # include <stdio.h>
  2. # include <malloc.h>
  3. void f(int *pArr, int i);
  4. void g(int *pArr, int i);
  5. int main(void)
  6. {
  7.     int i;
  8.     printf("请输入你要定义的数组大小:\n");
  9.     scanf("%d", &i);
  10.     int *p = (int *)malloc(sizeof(int) * i);
  11.     free(p); //上一行刚申请到的空间,这里马上就释放掉了???建议释放后要p=NULL;将p指向空指针
  12.     f(p, i); /*上一行free(p);已经把p指向的空间释放了,为什么这里还要去使用释放掉的空间???
  13.                为什么这里不出错?因为就算房子拆了,但是房子所在的那个地址,还是存在的
  14.                所以仍然可以使用那块空间,但是这样做是很危险的,所以要p=NULL */
  15.     g(p, i); //同上
  16.     free(p); //释放内存是正确的,但是!!千万不要对同一块空间释放2次!!!!
  17.     return 0;
  18. }
  19. void f(int *pArr, int i)
  20. {
  21.     printf("请输入数组每个数的值!\n");
  22.     int j;
  23.     for (j = 0; j < i; ++j)
  24.         scanf("%d", &pArr[j]);
  25.     printf("输入完毕!!\n");
  26. }
  27. void g(int *pArr, int i)
  28. {
  29.     int j = 0;
  30.     for (j = 0; j < i; ++j) //
  31.         printf("%d  ", pArr[j]);
  32. }
复制代码

补充内容 (2012-11-4 01:19):
int *p = (int *)malloc(sizeof(int) * i);
free(p);
不是说申请了不能马上释放,这是绝对没问题的
问题就只有2个:
1.释放了的空间再次使用
2.对同一块空间释放2次
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2012-11-4 00:17:15 | 显示全部楼层
因为第一次在论坛贴代码,可能个是有点乱,见谅
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2012-11-4 00:20:48 | 显示全部楼层
图没贴上,另上传了

ZH1QSTTJ0TEJO6O]8OUK2OE.rar

56.56 KB, 下载次数: 3

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2012-11-4 00:48:19 | 显示全部楼层
楼主的代码确实有点乱,我大概看了下,不明白楼主为什么要free两次,malloc和free必须成对出现的啊,你第一次free了,p所指向的对空间也就被释放了,就是说程序员不应该对这段空间在进行操作了,而且楼主的代码也非常不规范,命名就不说了,每次free(p)之后应该立马对p赋一个NULL值,这样可以起到检测错误的作用,因为在后面的程序中你仍然有可能对p进行操作,但p所指向的空间已经被释放了,这就不知道会造成什么后果了,后果可能是灾难性的,如果加上p = NULL这么一句的话,如果在之后的代码中你依旧对p进行了操作,程序一运行就会崩,会崩就是好事,说明你的程序有问题,弹出的错误代码会是C05,一看到这个错误代码有经验的人很快就能确定并修改代码。。。。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2012-11-4 01:14:57 | 显示全部楼层
:@使用了一个释放的空间,程序员必须要注意的一点就是这个!!!
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2012-11-4 12:18:03 | 显示全部楼层
  1. # include <stdio.h>
  2. # include <malloc.h>

  3. void f(int * pArr, int i);
  4. void g(int * pArr, int i);

  5. int main(void)
  6. {
  7.         int i;
  8.         printf("请输入你要定义的数组大小:\n");
  9.         scanf("%d", &i);
  10.         int * p = (int *)malloc(sizeof(int) * i);

  11.         f(p, i);
  12.         g(p, i);

  13.         free(p);        //在定义动态变量的时候,一定不要忘了释放内存

  14.         f(p, i);
  15.         g(p, i);

  16.         return 0;
  17. }

  18. void f(int * pArr, int i)
  19. {
  20.         printf("请输入数组每个数的值!\n");
  21.         int j;
  22.         for (j=0; j<i; ++j)
  23.                 scanf("%d", &pArr[j]);
  24.         printf("输入完毕!!\n");

  25. }

  26. void g(int * pArr, int i)
  27. {

  28. //        printf("%d\n", pArr[i-2]);

  29.         int j = 0;                /*
  30.                                         要是检查没有语法错误,就检查标点符号吧,
  31.                                         尤其是逗号和分号,还要注意是在英文状态下输入的
  32.                                         */
  33.         for (j=0; j<i; ++j)        //
  34.                 printf("%d  ", pArr[j]);

  35. }
复制代码
可能是第一次传的时候弄错了代码,就这一段代码而言,free()函数扔起不到释放内存的作用,free()后面的函数仍可以执行,???,还有,能否加QQ详问
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2012-11-4 12:30:00 | 显示全部楼层
飘香夜梦 发表于 2012-11-4 00:48
楼主的代码确实有点乱,我大概看了下,不明白楼主为什么要free两次,malloc和free必须成对出现的啊,你第一 ...
  1. # include <stdio.h>
  2. # include <malloc.h>

  3. void f(int * pArr, int i);
  4. void g(int * pArr, int i);

  5. int main(void)
  6. {
  7.         int i;
  8.         printf("请输入你要定义的数组大小:\n");
  9.         scanf("%d", &i);
  10.         int * p = (int *)malloc(sizeof(int) * i);

  11.         f(p, i);
  12.         g(p, i);

  13.         free(p);        //在定义动态变量的时候,一定不要忘了释放内存

  14.         f(p, i);
  15.         g(p, i);

  16.         return 0;
  17. }

  18. void f(int * pArr, int i)
  19. {
  20.         printf("请输入数组每个数的值!\n");
  21.         int j;
  22.         for (j=0; j<i; ++j)
  23.                 scanf("%d", &pArr[j]);
  24.         printf("输入完毕!!\n");

  25. }

  26. void g(int * pArr, int i)
  27. {

  28. //        printf("%d\n", pArr[i-2]);

  29.         int j = 0;                /*
  30.                                         要是检查没有语法错误,就检查标点符号吧,
  31.                                         尤其是逗号和分号,还要注意是在英文状态下输入的
  32.                                         */
  33.         for (j=0; j<i; ++j)        //
  34.                 printf("%d  ", pArr[j]);

  35. }
复制代码
free两次是代码上错了,我的问题是free函数没起到作用,没有释放内存,至于命名,刚学c,从网上下的教程还没看完,所以命名上有所失误,见谅,
十分感谢您的回答,以后注意
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2012-11-4 13:54:47 | 显示全部楼层
初行者 发表于 2012-11-4 12:30
free两次是代码上错了,我的问题是free函数没起到作用,没有释放内存,至于命名,刚学c,从网上下的教程还 ...
  1. # include <stdio.h>
  2. # include <malloc.h>

  3. void f(int * pArr, int i);
  4. void g(int * pArr, int i);

  5. int main(void)
  6. {
  7.         int i;
  8.         printf("请输入你要定义的数组大小:\n");
  9.         scanf("%d", &i);
  10.         int * p = (int *)malloc(sizeof(int) * i);

  11.         f(p, i);
  12.         g(p, i);

  13.         //在定义动态变量的时候,一定不要忘了释放内存
  14.         if (NULL != p)
  15.         {
  16.             free(p);
  17.             p = NULL;
  18.         }      

  19.         f(p, i);
  20.         g(p, i);

  21.         return 0;
  22. }

  23. void f(int * pArr, int i)
  24. {
  25.         printf("请输入数组每个数的值!\n");
  26.         int j;
  27.         for (j=0; j<i; ++j)
  28.                 scanf("%d", &pArr[j]);
  29.         printf("输入完毕!!\n");

  30. }

  31. void g(int * pArr, int i)
  32. {

  33. //        printf("%d\n", pArr[i-2]);

  34.         int j = 0;                /*
  35.                                         要是检查没有语法错误,就检查标点符号吧,
  36.                                         尤其是逗号和分号,还要注意是在英文状态下输入的
  37.                                         */
  38.         for (j=0; j<i; ++j)        //
  39.                 printf("%d  ", pArr[j]);

  40. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2012-11-4 14:01:58 | 显示全部楼层
帮楼主修改了,现在的代码再在后面使用p变量就会报错了,这是好事,因为报错了我们就会去修改它,如果现在不报错指不定哪天报错,如果你开发的软件是这样的话也许就玩大了,因为你想,如果你开发一个飞机导航系统,测试的时候一切正常,但是飞机上天的时候突然软件崩了,那不玩大了吗?

其实我之前就已经回答了楼主这个问题,楼主第一次贴的代码不仅仅是两次free的问题,free的时候没有判断,而且free之后p变量没赋空值我都有提过,只是楼主没有认真看而已。。。。。

我们为什么要这么做,我向楼主解释一下,int * p = (int *)malloc(sizeof(int) * i);

这句代码是向堆空间申请一段内存,并且让p指向这段内存,而之后的free(p)是收回这段堆内存,但是你要注意,p变量依然指向这段堆内存,也就是说我们依然能用p变量对这段堆内存进行操作,难道楼主不觉得这是灾难性的吗?因为如果后面你再申请一个指针变量p2也指向一段堆内存,但是第一次申请的已经被释放了,却没有对p赋空值的话,那么第二次申请的堆内存可能就和第一次申请的有重叠,那么通过p也可以修改p2所指向的堆内存里面的值,那这个程序运行下去的结果也许就无法估计了,因为连内存中的值已经被非法修改了。。。。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2012-11-4 18:51:51 | 显示全部楼层
初行者 发表于 2012-11-4 12:18
可能是第一次传的时候弄错了代码,就这一段代码而言,free()函数扔起不到释放内存的作用,free()后面的函 ...


free(p);
已经把p指向的空间释放了,为什么这里还要去使用释放掉的空间???
为什么这里不出错???

因为就算房子拆了,但是房子所在的那个地址,还是存在的,所以仍然可以使用那块空间。
但是这样做是很危险的,所以要p=NULL;

程序在执行到 int *p = (int *)malloc(sizeof(int) * i); 的时候,
在内存中获得了一块内存空间(买了一块地,没有盖房子),指针p指向这块内存空间(在还买了另一个小房子,在这个小房子的墙上,写有你买的那块地的地址)。

f(p, i); 的时候,在f()函数(施工队)中,向p指向的内存空间写入数据(让请来的施工队把房子建好)。


free(p); 的时候,
把p指向的内存空间释放了,这块空间就还给操作系统去管理,不属于本程序了,但是p指针还是你的,p仍然保存着那个地址。
(请free()这个中介把房子卖给ZF了,这房子不是你的了,但是你还有另一个小房子呀,里面有你卖给ZF的房子的地址)


f(p, i);
(又把f()施工队找来,根据p的地址,再次找到那块地,不管ZF将那块地弄成怎样,是改成公园还是游泳池,你都不管!反正你就要施工队把地夷为平地,再按你的要求,新建其它的)

return 0;
程序退出。ZF发现那块地变样了。。。
所以,是不能这么做的,尽管你对ZF有不满的地方。。。

***建议:在free(p)之后,要p=NULL;,把墙上的地址擦掉。

补充内容 (2012-11-4 18:52):






补充内容 (2012-11-4 18:52):
ZF = 政。府
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2012-11-4 21:49:11 | 显示全部楼层
向往 发表于 2012-11-4 18:51
free(p);
已经把p指向的空间释放了,为什么这里还要去使用释放掉的空间???
为什么这里不出错???

可能理解错我的意思了
能否加QQ详问312024054
备注加   鱼C
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-11-16 03:57

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表