上节内容中,我们学习如何规范的申请和使用动态内存
,其实是很重要的一环。
在大的程序中,应该注意这些细节问题,不然就会对其他的程序猿们产生影响,因为大的程序不可能交由一个人完成,所以,你编写的代码不够规范就有可能对后续的编写工作产生不良的影响。
今天,我们将学习在动态内存中常见的错误
,好了,话不多说,开整!!!!!
未经判定也就是说,没有判断向内存中的栈区申请空间这个操作是否成功,就使用了该部分内存
,这显然是不合理的,极易产生错误,如以下代码:
#include
#include
int main()
{
int* arr = (int*)malloc(10*__INT_MAX__);
int i = 0;
for(i=0;i<10;i++)
{
*(arr+i) = i;
printf("%d ",*(arr+i));
}
free(arr);
arr = NULL;
return 0;
}
其中的_INT_MAX_
代表着16进制数0x7fffffff,因此如此大的空间或许我们没有申请成功,但未经判断就在下面进行了使用,结果程序崩溃,如下:
如果我们进行判定,就会避免这个错误的产生,如下所示代码:
#include
#include
#include
int main()
{
int* arr = (int*)malloc(10*(__INT_MAX__));
int i = 0;
if (arr == NULL)
{
printf("%s\n",strerror(errno));
}
else
{
for(i=0;i<12;i++)
{
*(arr+i) = i;
printf("%d ",*(arr+i));
}
}
free(arr);
arr = NULL;
return 0;
}
编译查看结果:
编译器提醒我们,没有足够的动态内存空间,这样就不会执行赋值代码,程序自然就不会奔溃,因此,申请到的动态内存空间在使用前进行判定十分重要
。
越界访问
这个词,我们不是第一次听说了,在数组
中就存在着越界访问的问题,也就是没有那么大的地方,你非要访问那么大的地方,导致程序产生了错误,如以下代码:
#include
#include
#include
int main()
{
int* arr = (int*)malloc(40);
int i = 0;
if (arr == NULL)
{
printf("%s\n",strerror(errno));
}
else
{
for(i=0;i<11;i++)
{
*(arr+i) = i;
printf("%d ",*(arr+i));
}
}
free(arr);
arr = NULL;
return 0;
}
从上述代码中我们可以看到,向动态内存在申请了40字节的空间,但是在赋值是我们缺赋值了11个整型元素也即44字节,此时就会产生越界访问的问题
。
但是在vscode
下仍然没报错,看样子在这个编译器下,可能是编译器比较强(我猜的),因此就不演示了。
你明明没有使用动态内存定义,却对变量进行空间释放,就会产生错误
,如以下代码:
#include
#include
int main()
{
int a = 10;
int* p = &a;
free(p);
p = NULL;
return 0;
}
只是在栈区
上定义了一个变量,你却对他进行了内存释放,显然不合理,因此也会产生错误,但是该从代码在VScode
下,也正常编译了,因此在Linux
下演示效果,编译结果如下:
先上代码如下:
#include
#include
int main()
{
int* p = (int*)malloc(40);
int i = 0;
if (p == NULL)
{
return 0;
}
else
{
for(i=0;i<5;i++)
{
*p++ = i;
}
}
free(p);
p = NULL;
return 0;
}
我们进行分析:在申请了动态内存后,判断,进行循环赋值,然后进行释放,但是其实在释放是就产生了问题,如下图:
再赋值完后,p指向的已经不再是最初的地址,因此对对其进行释放,将会释放此地址后的40个字节的内存,我们在Linux
下编译运行,如下:
可见,释放一部分动态内存空间也会产生错误
。
这个就比较好理解了,你再释放完后,又给人释放了,这叫什么事,代码如下:
#include
#include
int main()
{
int* p = (int*)malloc(40);
if (p == NULL)
{
return 0;
}
else
{
int i = 0;
for(i=0;i<10;i++)
{
*(p+i) = i;
}
}
free(p);
free(p);
p = NULL;
return 0;
}
这个就更好理解了,在上节课就介绍过了,就不再此处重复讲解了,请大家回看上节内容。
上述内容即使今天的全部内容了,感谢大家的观看。
如果方便,辛苦大家点个赞和关注哦!
您的点赞或评论或关注是对我最大的肯定,谢谢大家!!!