当前位置:网站首页>C语言——动态内存分配常见的错误案例

C语言——动态内存分配常见的错误案例

2022-08-11 05:16:00 云逸943

前言

        关于在堆区动态开辟内存空间,我介绍了三种函数的基本讲解和使用方法,有兴趣的小伙伴可以去看看我对动态内存分配的函数讲解:C语言动态内存分配(1)三种函数讲解_.。接下来我会讲一讲我们在使用动态内存分配时常见的几种错误案例。

常见错误1:对NULL指针的解引用操作

#include<stdlib.h>
#include<stdio.h>


int main() {
	int* ptr = (int*)malloc(40);
	*ptr = 20;
	free(ptr);
	return 0;
}

        如上图代码,案例中通过创建指针去接收malloc动态开辟的40字节内存,然后直接用来解引用操作 。这种方法有些危险,万一动态开辟内存失败,malloc会返回空值,那么*ptr就会成为空指针,空指针不可进行解引用操作!所以每次动态开辟进行指针接收时,应该加以判断,若指针为空,表明开辟失败,return -1;若开辟成功,则可以进行解引用等其他操作。

      注:  return表示返回值,如果在程序中有void就不用return他表示返回值为空,在常使用的return时会用到return -1,return 0,return 1等。若按照实际程序的意思返回0,0则代表程序正常退出,否则代表程序异常退出。基本上-1表示false, 0为ture。

解决方案:

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<errno.h>

//解决方法:
int main() {
	int* ptr = (int*)malloc(40);

//判断指针是否为空
	if (ptr == NULL) {
		printf("%s\n", strerror(errno));
		return -1;//异常出错
	}

	*ptr = 20;
	//释放动态内存
	free(ptr);
	ptr = NULL;
	return 0;
}

 


 

 常见错误2:对动态开辟空间的越界访问

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<errno.h>

int main() {
	int* p =(int*)malloc(40);

    	if (ptr == 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;
}

         代码讲解:案例中动态开辟了创建了40字节的空间,强转为int*表示开辟了40*4=10个整型空间,通过循环赋值,为10个整型空间赋值1~10,但多写了一次循环,导致造成空间越界访问,出错!

        解决方法:要通过开辟的内存字节数,正确选定循环次数,万不可造成内存空间的越界!


常见错误3:3 对非动态开辟内存使用free释放

#include<stdlib.h>
#include<stdio.h>
int main{
    int a=10;
    int* p=&a;
    free(p);
    p=NULL;
    return 0;
}

        代码讲解:案例中通过对变量a赋值,使用指针获取a的地址,进而释放指针p的内存。

                          前两条语句是在栈区开辟的内存,属于静态开辟方式。而free函数是专门处理在堆区开辟的内存 ,属于动态开辟释放。牛头不对马嘴,所以出错。

        解决方法:去掉free(p);p=NULL;等两条语句。


常见错误4.使用free释放一块动态开辟内存的一部分

#include<stdlib.h>
#include<stdio.h>
int main() {
	int* p = (int*)malloc(40);
    //......判断
	int i = 0;
	for (i = 0; i < 10; i++) {
		printf("%d ",*p);
		p++;
	}
	free(p);
	p = NULL;
	return 0;
}

        代码讲解:案例中通过指针接收malloc开辟的40字节内存,通过循环遍历的方式,输出10个整型空间的值 ,随着指针的向后跳转,最后释放了指针p,p被置为空。

        在代码最后:释放的指针P的内存并不是由malloc开辟的40字节内存,释放的是指针p之后的内存空间,如下图:

 

        等循环结束后,p++已经使p指向了malloc开辟40字节的末尾地址,free(p)只会释放掉一丢丢内存,而我们需要释放掉整40字节开辟的内存空间,所以出错 !指针p不该乱动!!!

        解决方案:

#include<stdlib.h>
#include<stdio.h>

//解决方法:
int main() {
	int* p = (int*)malloc(40);
	int i = 0;
    //....判断
	for (i = 0; i < 10; i++) {
        //方案1:
		//*(p + i) = i;
		//printf("%d ",*(p + i));
		
		//方案2:
		p[i] = i;
		printf("%d ", p[i]);
	}
	free(p);
	p = NULL;
	return 0;
}

        注:方案1中*(p+i)动的只是i。 

 


常见错误5:对同一块动态内存多次释放

#include<stdlib.h>
#include<stdio.h>

int main() {
	int* p =(int*) malloc(40);
	//.......
	free(p);
	//......
	free(p);
	p = NULL;
	return 0;
}

        案例中对malloc开辟的40字节空间共采用了两次空间释放函数,重复释放,造成程序异常。

        对于开辟的一次动态内存空间,只需要执行一次free函数即可 。

解决方案:

#include<stdlib.h>
#include<stdio.h>

int main() {
	int* p = (int*)malloc(40);
	//.......
	free(p);
	p = NULL;
	free(p);
	return 0;
}

        第一次释放后执行指针置空语句,即使我们忘记之前free过,又free了一次也无妨,因为free遇到空指针时,不会执行任何操作。 


常见错误6:动态开辟内存忘记释放——内存泄露 

#include<stdlib.h>
#include<stdio.h>

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

        代码讲解:在test函数内部动态开辟了一次内存空间,由于疏忽忘记释放,所以会一直消耗内存, 在test函数调用完毕后,直接被销毁,虽然动态开辟的空间还在,但却永远也找不到malloc开辟的那块内存的位置。

        解决方案:

#include<stdlib.h>
#include<stdio.h>
//解决方法:
void test()
{
	int* p = (int*)malloc(100);
	if (NULL != p)
	{
		*p = 20;
	}
	free(p);
	p = NULL;
}
int main()
{
	test();
	while (1);
}

切记:动态开辟的空间一定要释放,并且正确释放

好了,以上就是我们在使用动态内存分配时常写错的一些案例,大家觉得有用的话,点一点三连吧,谢谢大家,再见!

原网站

版权声明
本文为[云逸943]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_69283129/article/details/126120351