【C语言】动态内存函数的详细讲解2:常见的动态内存使用的错误

上一篇文章为大家详细讲解了动态内存函数的简单的使用,并用图例为大家演示了空间的问题。https://blog.csdn.net/wangduduniubi/article/details/129756824?spm=1001.2014.3001.5502

本篇内容也为大家总结几点动态内存使用时经常出现的错误,希望能对大家有所帮助。

目录

1.对NULL指针(空指针)的解引用操作

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

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

4.使用free释放动态内存空间的一部分

5.对同一块动态内存空间的多次释放

6.开辟动态内存空间后没有释放


1.对NULL指针(空指针)的解引用操作

我们在上篇的讲解中讲解了malloc开辟出一段空间后要对其进行判断,我们上代码举例讲解动态分配时的错误

#include<stdio.h>
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指针。所以当我们写出上面这段代码时,能不能运行就完全看我们的运气了,所以这样的代码是有漏洞的

 我们可以看到编译器也觉得这段代码有点不太合适,所以使用在使用动态内存函数时要对其的返回类型进行判断。

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

这个错误不难理解,就是字面意思,如果你使用的空间超过了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个字节的空间,所以就会报错

所以注意,越界访问也是有问题的。

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

我们在使用free函数时之前并没有使用动态内存函数开辟空间,所以也没有必要稀里糊涂的使用free函数来手动释放这块空间

以下为示例的错误代码

int main()
{
	int arr[10] = { 0 };
	int* p = arr;
	free(p);
	p = NULL;
	return 0;
}

以下是运行结果

 可以看到程序会直接报错

所以在写代码时一定要注意,千万不要酒后写代码。

4.使用free释放动态内存空间的一部分

这样的错误情况也非常的常见

以下是错误代码示范

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就自然不能将这段空间释放。就好比一个人在成长时忘记了它=他最最最初的本心,越走越远。

5.对同一块动态内存空间的多次释放

这中错误也是字面意思

当我们在使用申请的空间时释放了一次;

最后还释放了一次就会报错

以下是错误代码

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一个空指针的时候,什么事情也不会发发生,不过大家在写代码时还是要小心为上。

6.开辟动态内存空间后没有释放

首先要说明的是如果使用动态内存函数开辟空间后,没有使用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;
}

运行起来,不要将运行后的黑框关掉,再打开任务管理器找到编译器所占用的空间

可以看到当代码运行起来后,暂时没有将运行框关闭,为了让大家能更加直观的看到任务管理器中程序消耗的内存,我用红色的矩形框了起来,可以看到内存消耗非常非常大,原因是程序没有释放,一直在申请空间,内存:什么动静?

当我们将程序关闭时

 所占用的内存就由系统释放掉了,希望大家能够注意。

以上就是为大家整理出来的动态内存使用时常见的错误,如果觉得文章对您有帮助,不妨三连支持一下,感谢您的阅读。

猜你喜欢

转载自blog.csdn.net/wangduduniubi/article/details/129783762