在子函数中malloc分配内存和free释放内存的方法(基于C)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hnxyxiaomeng/article/details/84793462

1. 子函数malloc分配内存

       为了增强程序可读性,有时会在子函数中malloc分配内存。测试了如下三种方法,容易想到的是第一种。事实证明这种也是错误的!

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

typedef struct _dataStc
{
	int buf[100];
	int size;
}dataStc;

void func1(dataStc* p)
{
	p = (dataStc*)malloc(sizeof(dataStc));
	p->size = 10;
	return;
}

dataStc* func2(void)
{
	dataStc* p;
	p = (dataStc*)malloc(sizeof(dataStc));
	p->size = 10;
	return p;
}

void func3(dataStc** p)
{
	*p = (dataStc*)malloc(sizeof(dataStc));
	(*p)->size = 10;
	return;
}

int main(int argc, const char * argv[]) {
	
	dataStc *p1 = NULL;
	dataStc *p2 = NULL;
	dataStc *p3 = NULL;

	func1(p1);
	p2 = func2();
	func3(&p3);

	if (p1 == NULL)
	{
		printf("p1=NULL\n");
	}
	else
	{
		printf("p1->size:%d\n", p1->size);
	}
	if (p2 == NULL)
	{
		printf("p2=NULL\n");
	}
	else
	{
		printf("p2->size:%d\n", p2->size);
	}
	if (p3 == NULL)
	{
		printf("p3=NULL\n");
	}
	else
	{
		printf("p3->size:%d\n", p3->size);
	}
	return 0;
}

执行结果如下所示:

p1=NULL
p2->size:10
p3->size:10

结论:只有后两种方法能正确分配内存。即直接返回内存指针,或将二级指针作为参数传入子函数。这是因为,在子函数中,内存指针只是被当做一个变量来处理的(虽然这个变量被定义为dataStc *),对其赋值后再返回,它的值当然没改变。

另外,由于成员选择运算符“->”的优先级比取值运算符“*”高,所以在func3中,*p需要加括号。

2. 子函数free释放内存

在子函数中释放内存,很容易想到的是写个下面这样的函数释放内存:

void func_free(dataStc* p)
{
	free(p);
	return;
}

上面的函数能释放内存,但也有个缺陷。因为C在free一段内存后,该内存的确是被释放了(可以被其他程序使用),但指针p仍然指向该段内存(而不是我们期待的NULL)。这时p就成为野指针了(不同于空指针),仍然可以访问或修改p指向的内存。如果其他程序不慎又通过p访问了内存,程序或许不报错,但可能带来不可预知的后果。

因此,保险做法是,在free后,将p赋为NULL。由于这里又将输入变量p修改了,因此仍然需要传递二级指针。正确的代码为:

void func_free(dataStc** p)
{
	free(*p);
	*p = NULL;
	return;
}

这样,在其他程序中访问p时,就可先判断其是否为NULL了。

猜你喜欢

转载自blog.csdn.net/hnxyxiaomeng/article/details/84793462