Sta*_*ack 5 c c++ pointers memory-management dangling-pointer
在堆栈中,保留了内存main,我们称之为main函数的堆栈帧.
当我们调用该Add函数时,内存保留在堆栈顶部.在Add函数的堆栈帧,a并且b是本地指针和c是计算的整数,然后我们返回参考.c是Add函数的局部变量.
现在当Add函数执行完成时,堆栈中的内存空间也被释放,所以当我们尝试在mainwith指针中访问这个地址时p,我们试图访问的内容基本上是一个释放空间.编译器发出警告,但为什么它仍然正确打印值5?
答案可能是机器没有释放内存空间,因为它没有必要,因为没有更多的功能.但是如果我们编写另一个函数,Hello那么它肯定应该释放Add调用堆栈中的函数空间,但程序仍会打印
Yay 5
Run Code Online (Sandbox Code Playgroud)
是因为像在堆中我们需要null在释放它之后指定一个指针,否则我们仍然可以访问它?有类似的东西吗?
/* void Hello()
{
printf("Yay");
} */
int* Add(int *a,int *b)
{
int c=*a+*b;
return &c;
}
int main()
{
int a=1,b=4;
int *p=Add(&a,&b);
// Hello();
printf("\t%d",*p);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
假设c是局部int变量,c在函数调用之后访问是undefined-behavior可以打印预期结果,或者可能做一些意外的事情.
虽然C不强制要求,但通常使用堆栈实现.出于性能原因,当函数返回时,它会使堆栈区域保持不变.这就是你看到价值的原因,5即1+4.但你永远不要指望这一点.
当您使用第二个函数时,行为仍然未定义,因此您可以获得任何输出.实际上,如果在第二个函数中定义另一个变量并使用它,输出可能会改变.
+-----------------+
.(local variables).
|'''''''''''''''''|
| |
+----------------+ . PRINTF FUNCTION .
| c = 42 | | |
|''''''''''''''''| +-----------------+
| | | |
. ADD FUNCTION . . HELLO FUNCTION .
| | | |
+----------------+ +-----------------+
| b = 4 | | b = 4 |
|''''''''''''''''| |'''''''''''''''''|
| a = 1 | | a = 1 |
|''''''''''''''''| |'''''''''''''''''|
| | | |
. MAIN FUNCTION . . MAIN FUNCTION .
| | | |
+----------------+ +-----------------+
Run Code Online (Sandbox Code Playgroud)
在上面的图中,我尝试直观地表示当你在Add函数和Hello函数内部时堆栈可能如何堆叠.你可以看到,Hello不与被保留用于堆栈内存搞乱c的Add功能.
您可以通过将Hello函数重写为来验证这一点
void Hello()
{
int i = 42;
printf("Yay - %d\n", i);
}
Run Code Online (Sandbox Code Playgroud)
可以打印42在main.