【C语言】常见的动态内存的错误

前言

在动态内存函数的使用过程中我们可能会遇到一些错误,这里将常见的错误进行总结。

对NULL解引用

请看以下代码:

可以看到,这时我们的malloc开辟是失败的,所以返回的是空指针NULL,而我们却没有进行检查,而是直接对其解引用,最终想要打印这块内存的内容,也是失败的。

这里的下波浪线是vs给出的没有进行检查的警告,即使malloc申请的空间没有那么大可以成功申请,最终也能正常打印,这个警告依然会存在

总之,就是不要忘记检查返回值是否为NULL。

对动态开辟空间的越界访问

动态开辟的空间也有自己的大小,所以也有越界。

可以看到,此时vs很智能地给出了警告。 

对非动态开辟内存使用free释放

int main()
{
	int a = 2077;
	int* p = &a;
	free(p);
	p = NULL;

	return 0;
}

这段代码中,p指向的明明不是动态开辟来的空间,却对它进行free,会发生什么呢?

可以看到会出现这样的后果。(动态内存相关的错误常见现象)

 

使用free释放动态开辟内存的一部分

我们知道,如果用*(p+i),在访问数组的过程中,i在改变,但p始终没有改变。

int* p = (int*)malloc(10*sizeof(int));
if (p == NULL)
{
	perror("malloc");
	return 1;
}

int i = 0;
for(i=0;i<5;i++)
{
    *(p+i)=i;
}

free(p);
p=NULL;

而我们还有另一种移动指针的写法:

int* p = (int*)malloc(10*sizeof(int));
if (p == NULL)
{
	perror("malloc");
	return 1;
}

int i = 0;
for(i=0;i<5;i++)
{
    *p=i;
    p++;
}

free(p);
p=NULL;

在这种写法中,p自身发生了改变。当退出循环时,由于p++,此时我们的p指向的是第6个元素(数组只有5个元素)。所以我们的p现在不指向动态开辟内存的起始位置。而使用free必须是传起始地址。

所以,我们不应该让p乱动

对同一块动态内存多次释放

如果是这样的多次释放:

free(p);
p = NULL;

free(p);
p = NULL;

这倒是没什么问题,因为前面已经把p置为NULL了,而对NULL进行释放会什么都不做。

但如果是这样的多次释放,就会有问题:

free(p);

free(p);
p = NULL;

因为我们并没有把p置为NULL,那么此时p成为了野指针,我们对野指针进行释放,这是有问题的。

所以又可以再次看出,将p释放后及时置为NULL的重要性。

动态开辟内存忘记释放(内存泄漏)

这是各类问题中相当令人头疼的一个。开辟了内存,也使用了,但是忘记释放了。

比如,我们在调用free()之前写了会提前返回的代码(这是很有可能发生的):

void test()
{
	int flag = 1;
	int* p = (int*)malloc(100);
	if (p == NULL)
	{
		return;
	}
	//假设这里使用了这块内存
	if (flag)//假设某个条件发生了,就提前返回
		return;
	free(p);
	p=NULL;
}

int main()
{
	test();
	//假设这里还有很多代码
	return 0;
}

所以这时,我们开辟来的这块空间没有机会释放了。

而且从test回到主函数后,还有很多代码,已经找不回这块空间了,也就是内存泄漏了。

只有等到主函数彻底结束,这块空间才会回收。

内存泄漏指的是一块空间动态开辟后,使用完又不释放,也可能再没法释放,这块空间就相当于消失或者说泄漏了。

所以可以看到,即使我们的malloc和free已经成对使用了,也有可能出现无法释放的情况,这样的内存泄漏的问题必须在写代码时小心,在出问题时也得慢慢去查。

(如果想让后面的程序去释放,那就要把指针返回给后面的程序)

 内存泄漏有多可怕呢,比如一些服务器程序,24/7,一直在运行,如果内存泄漏,一会吃掉一点内存,可能就把内存耗干了,机器就挂了。

总结

动态内存是一把双刃剑,能够提供灵活的内存管理方式,同时也会带来风险。

到此,本文就结束了,祝阅读愉快^_^

相关推荐

  1. C++动态

    2024-06-06 06:36:03       37 阅读
  2. C语言】变量占用大小&&内存对齐

    2024-06-06 06:36:03       13 阅读
  3. c++ 动态分配

    2024-06-06 06:36:03       19 阅读
  4. c语言常见错误

    2024-06-06 06:36:03       22 阅读
  5. C语言共享

    2024-06-06 06:36:03       11 阅读
  6. C# 分配管理

    2024-06-06 06:36:03       41 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-06 06:36:03       19 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-06 06:36:03       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-06 06:36:03       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-06 06:36:03       20 阅读

热门阅读

  1. 从0开始读C++Primer|第一章 开始

    2024-06-06 06:36:03       7 阅读
  2. Prompt示例

    2024-06-06 06:36:03       9 阅读
  3. MYSQL

    MYSQL

    2024-06-06 06:36:03      8 阅读
  4. 撸广告小游戏开发app源码搭建

    2024-06-06 06:36:03       9 阅读