C 语言

关注公众号 jb51net

关闭
首页 > 软件编程 > C 语言 > C语言动态内存错误

C语言中常见的六种动态内存错误总结

作者:烽起黎明

学习过C语言中的动态内存函数,例如【malloc】、【calloc】、【realloc】、【free】,那它们在使用的过程中会碰到哪些问题呢,本本文我们一起来探讨下,感兴趣的朋友跟着小编一起来看看吧

1、对NULL指针的解引用操作

代码:

void test()
{
    int *p = (int *)malloc(INT_MAX/4);
    *p = 20;	//如果p的值是NULL,就会有问题
    free(p);
}

分析:

在这里插入图片描述

改进:

void test()
{
    int* p = (int*)malloc(INT_MAX / 4);
    if (NULL == p)
    {
        perror("fail malloc");
        exit(-1);
    }
    *p = 20;//如果p的值是NULL,就会有问题
    free(p);
}

在这里插入图片描述

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

代码:

int main(void)
{
	int* p = (int*)malloc(100);
	if (NULL == p)
	{
		perror("malloc fail");
		exit(-1);
	}

	int i = 0;
	for (int i = 0; i < 100; i++)
	{
		*(p + i) = 0;	// 当i == 25时便会越界
	}
	free(p);
	p = NULL;
	return 0;
}

分析:

在这里插入图片描述

在这里插入图片描述

其实我们可以将*(p + i) = 0修改成p[i] = 0,利用[]操作符对某个下标进行访问,此时我们可以看到编译器就报出了警告说索引"99"超出了“0"至”24"的有效范围,因此100个字节的空间只能供25个整型来进行存放,因此合法的下标索引即为0 ~ 24

在这里插入图片描述

改进:

int* p = (int*)malloc(100 * sizeof(int));

这个时候我们就可以看到没有警告再报出来了

在这里插入图片描述

3、对非动态开辟内存进行free释放

代码:

void test()
{
	int a = 10;
	int* p = &a;
	free(p);	//ok?
}

分析:

在这里插入图片描述

改进:

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

代码:

void test()
{
    int* p = (int*)malloc(100);
    if (NULL == p)
    {
    	perror("malloc fail");
    	exit(-1);
    }
    for (int i = 0; i < 10; i++)
    {
        p++;
    }
    free(p);    //p不再指向动态内存的起始位置
}

分析:

从下图可以看出,因为free()函数需要做到申请多少释放多少,所以当其释放了一部分之后,就不够了,便造成了访问内存错误的问题

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

改进:

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

代码:

void test()
{
    int* p = (int*)malloc(100);
    //使用...
    free(p);

    //...
    free(p);	//重复释放
}

分析:

在这里插入图片描述

改进:

void test()
{
    int* p = (int*)malloc(100);
    //使用...
    free(p);
    p = NULL;   // 将不使用的指针置为NULL
    //...
    free(p);	//重复释放
}

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

代码:

void test()
{
	int* p = (int*)malloc(100);
	if (NULL != p)
	{
		*p = 20;
	}
}

int main()
{
	test();
}

分析:

💬 那有同学说:既然函数内部没有做释放的话我在调用结束后去free一下这个p不就好了

这句话其实就存在很大的问题,、对于一个在一个函数创建的变量,是处在当前这个函数所维护的栈帧中的,所以当这个函数调用结束后局部变量就会随着栈帧的销毁而不复存在,那此时我们再想去free()释放这块空间的时候,是无法访问到这个指针p的。因此要释放的话只能在函数内部进行才可以

改进:

void test()
{
	int* p = (int*)malloc(100);
	if (NULL != p)
	{
		*p = 20;
	}
	
	free(p);
	p = NULL;
}

但是它们两个成对出现就一定不会出现问题吗?

void test()
{
	int* p = (int*)malloc(100);
	if (NULL != p)
	{
		*p = 20;
	}
	if (1)
		return;		// 因为某些条件中途return了, 没到free()

	free(p);
}

int main()
{
	test();
}

总结与提炼

最后来总结一下本文所学习的内容

以上就是C语言中常见的六种动态内存错误总结的详细内容,更多关于C语言动态内存错误的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文