3.1对NULL指针的解引用操作

#include <stdlib.h>
int main()
{
	int* p = (int*)malloc(20);
	//可能会出现对NULL指针的解引用操作
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		p[i] = i;
	}
	free(p);
	p = NULL;	

	return 0;
}

动态内存管理——常见的动态内存错误_malloc

当我们这样写代码的时候,可以看到编译器报了一个警告:取消对NULL指针“p”的引用。

就是说,如果 p 是NULL指针的话,0+0 再解引用(此时i=0),就会出现对NULL指针的解引用操作,这样是非常危险的。所以malloc函数的返回值要判断。


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

#include <string.h>
#include <errno.h>
#include <stdio.h>
int main()
{
	int i = 0;
	int* p = (int*)malloc(20);
	if (NULL == p)
	{
		printf("%s\n", strerror(errno));
		return 1;
	}
	//越界访问
	for (i = 0; i < 10; i++)
	{
		p[i] = i;
	}
	free(p);

	return 0;
}

当出现对动态开辟空间的越界访问的时候,程序运行起来之后就会崩溃(什么都不打印,过几秒后自动结束运行)。


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

int main()
{
	int arr[10] = { 1,2,3,4,5 };
	int* p = arr;
	//......对arr数组进行了什么什么操作
	free(p);
	p = NULL;
	return 0;
}

如果你某一天写代码的时候,喝了点小酒,对指向一个数组的指针进行了free,那么程序同样也会崩溃:

动态内存管理——常见的动态内存错误_malloc_02


3.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 + 1;
	}
	free(p);
	p = NULL;
	return 0;
}

这时p已经不再指向动态内存的起始位置,而是指向了中间位置,这是对p进行释放,程序也会崩溃:

动态内存管理——常见的动态内存错误_free_03


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

int main()
{
	int* p = (int*)malloc(20);
	if (p == NULL)
	{
		printf("%s\n", strerror(errno));
		return 1;
	}
	//使用
	free(p);
	//释放
	free(p);
	p = NULL;

	return 0;
}

这时程序也会崩溃:(但是如果之前把p置为NULL了,就不会崩溃,因为free空指针的话,什么也不会发生)

动态内存管理——常见的动态内存错误_free_04


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

  对于malloc,calloc,realloc函数所申请的空间 ;如果不想使用,需要free释放,如果不适用free释放,程序结束后,也会由操作系统回收;但是,如果不使用free释放,程序也没有结束,就会导致内存泄漏。