上一篇文章为大家详细讲解了动态内存函数的简单的使用,并用图例为大家演示了空间的问题。https://blog.csdn.net/wangduduniubi/article/details/129756824?spm=1001.2014.3001.5502
本篇内容也为大家总结几点动态内存使用时经常出现的错误,希望能对大家有所帮助。
目录
1.对NULL指针(空指针)的解引用操作
2.对动态开辟空间的越界访问
3.对非动态开辟内存使用free释放
4.使用free释放动态内存空间的一部分
5.对同一块动态内存空间的多次释放
6.开辟动态内存空间后没有释放
我们在上篇的讲解中讲解了malloc开辟出一段空间后要对其进行判断,我们上代码举例讲解动态分配时的错误
#include
int main()
{
int* p = (int*)malloc(20);
int i = 0;
for (i = 0; i < 5; i++)
{
p[i]=i;
printf("%d", p[i]);
}
free(p);
p = NULL;
return 0;
}
上面的代码中取少了对指针的判断,函数的返回类型是个指针类型,我么们不能保证malloc在开辟空间时是否开辟成功,如果开辟失败的话就会返回一个空指针,也就是题目所说的NULL指针。所以当我们写出上面这段代码时,能不能运行就完全看我们的运气了,所以这样的代码是有漏洞的
我们可以看到编译器也觉得这段代码有点不太合适,所以使用在使用动态内存函数时要对其的返回类型进行判断。
这个错误不难理解,就是字面意思,如果你使用的空间超过了malloc申请的空间,那也是不可以的,程序会直接崩掉;我们用一串错误的代码来观察一下
int main()
{
int* p = (int*)malloc(20);
if (p == NULL)
{
printf("%s\n", strerror(errno));
return 1;
}
int i = 0;
for (i = 0; i < 10; i++)
{
p[i] = i;
}
free(p);
p = NULL;
return 0;
}
运行结果是这样的
可以看到下面的报错信息中告诉我们:我们越界访问了
我们只申请了20个字节的空间,但是在for循环遍历1~10,使用了40个字节的空间,所以就会报错
所以注意,越界访问也是有问题的。
我们在使用free函数时之前并没有使用动态内存函数开辟空间,所以也没有必要稀里糊涂的使用free函数来手动释放这块空间
以下为示例的错误代码
int main()
{
int arr[10] = { 0 };
int* p = arr;
free(p);
p = NULL;
return 0;
}
以下是运行结果
可以看到程序会直接报错
所以在写代码时一定要注意,千万不要酒后写代码。
这样的错误情况也非常的常见
以下是错误代码示范
int main()
{
int* p = (int*)malloc(40);
if (p == NULL)
{
printf("%s\n", strerror(errno));
return 1;
}
//使用
int i = 0;
for (i = 0; i < 5; i++)
{
p[i] = i + 1;
p++;
}
free(p);
p = NULL;
return 0;
}
在这段代码中我们可以看到malloc函数开辟了40个字节的空间,使用for循环遍历1~5时,只访问了二十个空间的内容,剩下二十个空间的内容还没有访问,就使用free函数将其释放掉了,运行起来看看结果怎样;
我们可以看到程序还是崩溃掉了,什么原因呢?
道理也很简单我们在使用的时候,随着p++的增长,指针p已经指向了数组下标元素为5的元素,但是free函数只能释放起始位置的空间,所以free就自然不能将这段空间释放。就好比一个人在成长时忘记了它=他最最最初的本心,越走越远。
这中错误也是字面意思
当我们在使用申请的空间时释放了一次;
最后还释放了一次就会报错
以下是错误代码
int main()
{
int* p = (int*)malloc(40);
if (p == NULL)
{
printf("%s\n", strerror(errno));
return 1;
}
//使用
free(p);
//释放
free(p);
return 0;
}
运行结果就是这样的
但是要注意的是如果我们在第一次释放完之后,将p的指针内容设为空,也就是将p设为空指针,那么在最后释放p的时候也不会报错
因为我们前面讲过free一个空指针的时候,什么事情也不会发发生,不过大家在写代码时还是要小心为上。
首先要说明的是如果使用动态内存函数开辟空间后,没有使用free将申请的空间释放后,在程序结束后,操作系统会自动释放空间。
如果使用空间后,没有使用free将申请的空间释放,并且程序也没有结束,那么就会出现漏内存的情况;
下面是一段使用空间后没有释放的代码:
void test()
{
int* p = (int*)malloc(20);
}
int main()
{
test();
return 0;
}
我们在另一个函数中申请一块空间,这个程序走到return 0那一步时,test函数中申请的空间没有在函数内部得到释放,并且出了函数后,函数本身也忘记了自己申请的20个字节的空间在哪儿了,这时就会造成内存泄漏。
所以自己申请的空间要尽量自己释放,自己不方便释放的空间,要告诉别人释放,这样就避免内存泄漏的问题。
接下来给大家看一下内存泄露的可怕之处
以下是为大家展示的内存泄漏的代码
int main()
{
while (1)
{
malloc(20);
}
return 0;
}
运行起来,不要将运行后的黑框关掉,再打开任务管理器找到编译器所占用的空间
可以看到当代码运行起来后,暂时没有将运行框关闭,为了让大家能更加直观的看到任务管理器中程序消耗的内存,我用红色的矩形框了起来,可以看到内存消耗非常非常大,原因是程序没有释放,一直在申请空间,内存:什么动静?
当我们将程序关闭时
所占用的内存就由系统释放掉了,希望大家能够注意。
以上就是为大家整理出来的动态内存使用时常见的错误,如果觉得文章对您有帮助,不妨三连支持一下,感谢您的阅读。