【C语言进阶:动态内存管理】常见的动态内存错误

本节重点内容:

  • 对NULL指针的解引用操作
  • 对动态开辟空间的越界访问
  • 对非动态开辟内存使用free释放
  • 使用free释放一块动态开辟内存的一部分
  • 对同一块动态内存多次释放
  • 动态开辟内存忘记释放(内存泄漏)
  • 经典的笔试题

⚡对NULL指针的解引用操作

【C语言进阶:动态内存管理】常见的动态内存错误_第1张图片


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

【C语言进阶:动态内存管理】常见的动态内存错误_第2张图片


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

【C语言进阶:动态内存管理】常见的动态内存错误_第3张图片


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

【C语言进阶:动态内存管理】常见的动态内存错误_第4张图片


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

【C语言进阶:动态内存管理】常见的动态内存错误_第5张图片


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

使用 malloc、calloc、realloc 函数申请的空间,如果不想使用,需要 free 释放,如果不使用 free 释放,在程序结束后,也会由操作系统进行回收。

如果没有使用 free 释放,程序也不结束,所申请的空间既没有使用,也没有释放,也没有回收,我们将这种情况称为内存泄漏

解决方法是:自己申请的,自己释放。自己不方便释放的,告诉别人进行释放。

【C语言进阶:动态内存管理】常见的动态内存错误_第6张图片


⚡经典的笔试题

题目1:请问运行Test 函数有哪些的错误?

#define _CRT_SECURE_NO_WARNINGS
#include 
#include
#include


void GetMemory(char* p)
{
	p = (char*)malloc(100);
}
int main()
{
	char* str = NULL;
	GetMemory(str);
	strcpy(str, "hello world");
	printf(str);
	return 0;
}

错误处:

  1. 调用 GetMemory 函数的时候,str 的传参为值传递,p 是 str 的临时拷贝,所以在GetMemory 函数内部将动态开辟空间的地址存放在 p 中的时候,不会影响 str 。所以 GetMemory 函数返回之后,str 中依然是 NULL 指针。strcpy 函数就会调用失败,原因是对 NULL 的解引用操作,程序会崩溃。
  2. GetMemory 函数内容 malloc 申请的空间没有机会释放,造成了内存泄漏。    

解决方案一:

#define _CRT_SECURE_NO_WARNINGS
#include 
#include
#include


char* GetMemory( )
{
	char* p = (char*)malloc(100);
	return p;
}
int main()
{
	char* str = NULL;
	str = GetMemory( );
	strcpy(str, "hello world");
	printf(str);
	free(str);
	str = NULL;
	return 0;
}

解决方案二:

void GetMemory(char** p)
{
	*p = (char*)malloc(100);
}
int main()
{
	char* str = NULL;
	GetMemory(&str);
	strcpy(str, "hello world");
	printf(str);
	free(str);
	str = NULL;
	return 0;
}

代码运行结果如下:

 题目2:请问运行Test 函数有哪些的错误?

#define _CRT_SECURE_NO_WARNINGS
#include 
#include
#include


char* GetMemory(void)
{
	char p[] = "hello world";
	return p;
}

int main()
{
	char* str = NULL;
	str = GetMemory();
	printf(str);
}

错误处:返回栈空间地址的问题

  1. GetMemory 函数内部有创建的数组是临时的,虽然返回了数组的起始地址给了 str ,但是数组的内存出了 GetMemory 函数就被回收了,而 str 依然保存着数组的起始地址,这时如果使用 str ,str 就是野指针。

解决方案:

#define _CRT_SECURE_NO_WARNINGS
#include 
#include
#include

char* GetMemory()
{
	static char p[] = "hello world";
	return p;
}

int main()
{
	char* str = NULL;
	str = GetMemory();
	printf(str);
}

代码运行结果如下:

题目3:请问运行Test 函数有哪些的错误?

#define _CRT_SECURE_NO_WARNINGS
#include 
#include
#include

void GetMemory(char** p, int num)
{
	*p = (char*)malloc(num);
}

void Test(void)
{
	char* str = NULL;
	GetMemory(&str, 100);
	strcpy(str, "hello");
	printf(str);
}
int main()
{
	Test();
	return 0;
}

错误处:内存泄漏

解决方案:

#define _CRT_SECURE_NO_WARNINGS
#include 
#include
#include

void GetMemory(char** p, int num)
{
	*p = (char*)malloc(num);
}

void Test(void)
{
	char* str = NULL;
	GetMemory(&str, 100);
	strcpy(str, "hello");
	printf(str);
	free(str);
	str = NULL;
}
int main()
{
	Test();
	return 0;
}

题目4:请问运行Test 函数有哪些的错误?

#define _CRT_SECURE_NO_WARNINGS
#include 
#include
#include

void Test(void)
{
	char* str = (char*)malloc(100);
	strcpy(str, "hello");
	free(str);
	if (str != NULL)
	{
		strcpy(str, "world");
		printf(str);
	}
}

int main()
{
	Test();
	return 0;
}

错误处:栈空间的非法访问

解决方案:

#define _CRT_SECURE_NO_WARNINGS
#include 
#include
#include

void Test(void)
{
	char* str = (char*)malloc(100);
	strcpy(str, "hello");
	free(str);
	str = NULL;
	if (str != NULL)
	{
		strcpy(str, "world");
		printf(str);
	}
}

int main()
{
	Test();
	return 0;
}

感谢大家能够看完这篇博客,创作时长,小伙伴们觉得我的博客对你有帮助,不妨留下你的点赞的收藏,关注我,带你了解不一样的C语言。

98b76a6f4a9c4ca88fd93da1188ac6f9.gif

你可能感兴趣的:(C语言进阶,c语言)