关于malloc()函数以及free()报heap buffer错误的问题

之前学过一学期的c语言,只是有个大概的概念。由于工作的转变,现在要重拾C语言。不过在学习的过程中难免会遇到各种问题,干脆就在每次遇到问题以及解决方法记录下来,以便自己查询,也方便遇到同样问题的初学者~


之前的小问题就不说了。
这次在尝试编写一个计算n个数的平均数的程序的时候,由于调用了malloc函数,在free()释放内存的时候遇到个错误:
CRT detected that the application wrote to memory after end of heap buffer。


虽然在编译完成以及计算和的时候没有什么问题,但总在free()的时候报内存错误,不得不中断程序,百度解决方案。

【PS:不要太指望你所谓的加入的群里能有多少大神回答你的问题,大神是没空在上班时间看qq的,除非工作交流所需。绝大多数我们还是自己百度、谷歌解决的好,既加深了你的印象,又不用太依赖他人~】



先贴出我的程序,再说说问题:


void main()
{
float ave;
int *a=NULL,m,i,j,s=0;
printf("请输入求和的数的个数:\n");
scanf_s("%d",&m);
a=(int*)malloc(m);
for(j=0;j<m;j++)//依次输入要求和的数
{
printf("请输入第%d个数:\n",j+1);
scanf_s("%d",&a[j]);
}
for(i=0;i<m;i++)//求和
{
s=s+a[i];
}
ave=s/(float)m;//求平均数
printf("%d个数的平均数为:%.5f\n",m,ave);//保留5位小数
free(a);
a=NULL;
system("pause");
}


这个程序在编译的时候是没多大问题的,也能正常的输入并计算。就是在输出了平均数之后,就会报错。如图:


不知道细心的你有没有发现问题。我当时是第一次使用这个函数,所以对这个函数了解不是很多。只是知道在注释掉free(a)和a=NULL这两行的时候程序是不会报错的【但是百度后才知道,不free掉有可能会造成内存溢出】。


错就错在malloc函数。下面是malloc函数的原型:
extern void *malloc(unsigned int num_bytes);
标准库里面的描述是:Returns pointer to uninitialised newly-allocated space for an object of size size, or NULL on error.【如果分配成功则返回指向被分配内存的指针,否则返回空指针NULL。】
与之相对应的是free函数:extern void free(void *p);【释放指针p所指向的的内存空间。】


对照程序,发现里面有两个错误:
1、所分配的空间的大小。
malloc只分配了m个字节的内存,而实际上该数组的每个元素需要4个字节(32位int型变量),数组总共需要m*4个字节。
这也是造成内存访问违规的直接错误。
2、未在申请了内存空间后检查是否分配成功。
我刚刚使用这个的时候是忽略了的。但是对于严谨的程序来说,这一步是必须检查的!关于分配失败的原因,应该有多种,比如说空间不足就是一种。


所以,程序的解决方法也出来了:添加malloc函数的内存分配检查;分配足够的内存!


下面是更改后的程序:
#include <stdio.h>
#include <stdlib.h> //包含malloc()和system()

void main()
{
float ave;
int *a=NULL,m,i,j,s=0;
printf("请输入求和的数的个数:\n");
scanf_s("%d",&m);
a=(int*)malloc(sizeof(int)*m);
if(NULL==a) //判断是否分配失败
{
exit(1);
}
for(j=0;j<m;j++)//依次输入要求和的数
{
printf("请输入第%d个数:\n",j+1);
scanf_s("%d",&a[j]);
}
for(i=0;i<m;i++)//求和
{
s=s+a[i];
}
ave=s/(float)m;//求平均数
printf("%d个数的平均数为:%.5f\n",m,ave);//保留5位小数
free(a);
a=NULL;
system("pause");
}

【当然,由于我还是新手,难免会有不严谨的地方,望指正!】

malloc函数的一些需要注意的地方【大神发给我的,没有注明出处。如有冒犯,请见谅~】:
A、申请了内存空间后,必须检查是否分配成功。
B、当不需要再使用申请的内存时,记得释放;释放后应该把指向这块内存的指针指向NULL,防止程序后面不小心使用了它。
C、这两个函数应该是配对。如果申请后不释放就是内存泄露(什么叫内存泄漏:简单的说就是申请了一块内存空间,使用完毕后没有释放掉。它的一般表现方式是程序运行时间越长,占用内存越多,最终用尽全部内存,整个系统崩溃。由程序申请的一块内存,且没有任何一个指针指向它,那么这块内存就泄露了);如果无故释放那就是什么也没有做。释放只能一次,如果释放两次及两次以上会出现错误(释放空指针例外,释放空指针其实也等于啥也没做,所以释放空指针释放多少次都没有问题)。
D、虽然malloc()函数的类型是(void *),任何类型的指针都可以转换成(void *),但是最好还是在前面进行强制类型转换,因为这样可以躲过一些编译器的检查。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值