计算机系统应用教程网站

网站首页 > 技术文章 正文

C++:深入研究关于函数返回指针的问题-理清栈数据回收机制

btikc 2024-09-12 12:07:43 技术文章 11 ℃ 0 评论

我想大家在学习函数的时候,教材都有提示大家C++函数返回的指针所指向的数据不能够是函数内声明的变量。这是为什么呢?而且我估计很多人在日常开发中还真有出现返回指向局部变量的指针的情况,并且还不知道后果的严重性。下面我们就一起来看看为什么C++教材会告诉我们不能这样。

测试

我们先看一段代码:

先定义一个返回指针的函数func()

int* func()
{
	int a = 100 ;//局部变量
	int *p = &a ;//指针p指向局部变量a
	return p ;//返回指向局部变量的指针
}

我们在main()函数中调用一下,并输出*p看下是什么结果:

int main()
{	
	int* p = func();
	cout<<"address p point to value:"<<*p<<endl;
	system("pause");
	return 0 ;
}

运行结果居然是:address p point to value:100;

what?什么情况?,这不是可以返回吗?为什么教科书告诉我不可以?难道教科书骗我?

别急,我们来看看内存情况:

修改func()方法,在func()中打印出变量a的地址:

int* func()
{
	int a = 100 ;
	int *p = &a ;
	cout<<"a address:"<<&a<<endl;
	return p ;
}

然后在main()中看p指向的地址是不是a的地址:

int main()
{	
	int* p = func();
	cout<<"address p point to value"<<*p<<endl;
	cout<<"address p point to :"<<p<<endl;
	system("pause");
	return 0 ;
}

我们可以看到,p指向的地址和系统分配给变量a的地址是同一块地址,但是为什么局部变量a在函数func()结束后没有被回收呢?还是可以被指针p访问到,并且地址上存的值也是对的呢?

了解栈内存回收机制

我们在main()中别急着输出*p,我们休息一下干点别的再去输出看会发生什么?

*p居然不是100。

这说明局部变量在出了作用域并不代表生命周期结束,只是被隐藏正常无法访问到了,如果通过其他手段还可以访问到,此时变量还并未出栈,等到真的出栈后就访问不到了,此时p就成了野指针,野指针的危害我想大家都知道。接下来我们就继续往下看,看看成为野指针的p到底会产什么什么影响。

这里我定义一个func2()函数,后面要调用:

void func2()
{
	int b = 110; 
	cout<<"b address:"<<&b<<endl;	
}

然后在mian()函数中调用:

int main()
{	
	int* p = func();
	cout<<"pause"<<endl;
	cout<<"address p point to value"<<*p<<endl;
	cout<<"address p point to :"<<p<<endl;
	func2();
	cout<<"address p point to value"<<*p<<endl;
	system("pause");
	return 0 ;
}

运行结果:

从结果看,p指向的地址一直没有变,都是原来的变量系统分配给变量a的内存,但是在a被栈回收后,在我们调用func2()的时候p所指向的内存又被分配给变量b了,这样就很危险了。

对b来说,就好比人家好不容易找到个媳妇发现她居然有老公。

对p来说,本来p认为它老婆18岁,最后发现居然是81岁(因为会被别人赋值)。

大家说这是不是很恐怖呢?

所以大家在写C++程序的时候,在指针处理环节一定要多多上心。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表