函数不能传递动态内存

<span style="background-color:#ffffff">下面这道面试题是有关指针、动态内存分配的相关内容,感觉比较经典,记录下来大家共享。</span>

问题

What will happen after running the "Test"?

#include <iostream>
using namespace std;
void GetMemory(char* p, int num)
{
	p = (char*)malloc(sizeof(char*)num);
};

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


分析

在上述例子中,毛病出在GetMemory中。函数中的形参*p实际上是主函数中str的一个副本,编译器总是要为函数的每个参数制作临时副本。在本例中,p申请了新的内存,只是把p所指的内存地址改变了,但是str丝毫未变。因为函数GetMemory没有返回值,因此str并不指向p所申请的那段内存,所以函数GetMemory并不能输出任何东西。事实上,每执行一次GetMemory函数就会申请一块内存,但申请的内存一直被独占,最终造成内存泄漏。

解决

如果一定要用指针参数去申请内存,那么应该采用指向指针的指针,传递str的地址给函数GetMemory。代码如下:

#include <iostream>
using namespace std;
void GetMemory(char** p, int num)
{
	*p = (char*)malloc(sizeof(char*)num);
};

int main()
{
	char* str = NULL;
	GetMemory(&str, 100);
	strcpy(str, "hello");
	cout << *str << endl;
	cout << str << endl;
	cout << &str << endl;
	return 0;
}

这样的话,程序就可以成功运行。字符串是一个比较特殊的例子,我们分别打印*str、str、&str可以发现,结果分别是h、hello、0*22f7c。str就是字符串的值,*str是字符串的首字符,&str是字符串的地址。

由于“指向指针的指针”这个概念不容易理解,我们可以用函数返回值来传递动态内存。这种方法更加简单,方法如下:

#include <iostream>
using namespace std;
char* GetMemory(char* p, int num)
{
	p = (char*)malloc(sizeof((char*)num));
	return p;
};

int main()
{
	char* str = NULL;
	str = GetMemory(str, 100);
	strcpy(str, "hello");

	cout << *str << endl;
	cout << str << endl;
	cout << &str << endl;

	return 0;
}


我们可以对这道题推而广之,看一下整型变量是如何传值的,代码如下:

#include <iostream>
using namespace std;
void GetMemory2(int* z)
{
	*z = 5;
};

int main()
{
	int v;
	GetMemory2(&v)
	cout << v << endl;
	
	return 0;
}

GetMemory把v的地址传了进来,*z是地址里的值,是v的副本。通过直接修改地址里的值,不需要有返回值,于是也把v给修改了,因为v所指向的地址的值发生了改变。

所以该题的答案是:程序崩溃。因为函数并不能传递动态分配的内存,主函数中的str一直都是NULL。

 

  • 12
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值