内存分配堆栈

Sta*_*ack 5 c c++ pointers memory-management dangling-pointer

在堆栈中,保留了内存main,我们称之为main函数的堆栈帧.

当我们调用该Add函数时,内存保留在堆栈顶部.在Add函数的堆栈帧,a并且b是本地指针和c是计算的整数,然后我们返回参考.cAdd函数的局部变量.

现在当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)

Moh*_*ain 8

假设c是局部int变量,c在函数调用之后访问是undefined-behavior可以打印预期结果,或者可能做一些意外的事情.

虽然C不强制要求,但通常使用堆栈实现.出于性能原因,当函数返回时,它会使堆栈区域保持不变.这就是你看到价值的原因,51+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不与被保留用于堆栈内存搞乱cAdd功能.

您可以通过将Hello函数重写为来验证这一点

void Hello()
{
  int i = 42;
  printf("Yay - %d\n", i);
}
Run Code Online (Sandbox Code Playgroud)

可以打印42main.

  • @MohitJain先生,最好的解释.+1.:-) (2认同)