内存分配堆栈

在堆栈中,存储器被保留用于main我们称之为堆栈帧main功能。

当我们调用Add函数时,内存保留在堆栈顶部。 在Add函数堆栈框架中, ab是局部指针, c是一个计算总和的整数,然后返回参考。 cAdd函数的局部变量。

现在,当Add函数执行完成时,堆栈中的内存空间也会被释放,所以当我们尝试访问main指针p中的这个地址时,我们试图访问的基本上是一个释放空间。 编译器会给出一个警告,但为什么它仍然正确输出值5?

答案可能是机器没有释放内存空间,因为它不认为它是必要的,因为没有更多的功能。 但是如果我们编写另一个函数Hello那么它肯定会为调用堆栈中的Add函数释放空间,但程序仍然会打印

Yay     5

是否因为像在堆中一样,我们需要在释放它之后指定一个指向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;
}

假设c是局部int变量,在函数调用之后访问cundefined-behavior并且可能会打印预期结果,或者可能会做出意想不到的事情。

虽然C没有强制执行,但通常使用堆栈实现。 出于性能原因,当函数返回时,它会保持堆栈区不变。 这就是你看到值51+4 。 但你永远不应该指望这一点。


当你使用第二个函数时,行为仍然是未定义的,所以你可以得到任何输出。 在实践中,如果在第二个函数中定义另一个变量并使用它,则输出可能会改变。

+----------------+
|  c = 42        |
|''''''''''''''''|     +----------------+
|                |     |                |
.  ADD FUNCTION  .     . HELLO FUNCTION .
|                |     |                |
+----------------+     +----------------+
|  b = 4         |     |  b = 4         |
|''''''''''''''''|     |''''''''''''''''|
|  a = 1         |     |  a = 1         |
|''''''''''''''''|     |''''''''''''''''|
|                |     |                |
.  MAIN FUNCTION .     .  MAIN FUNCTION .
|                |     |                |
+----------------+     +----------------+

在上面的图中,我试图直观地表示堆栈在Add函数和Hello函数内时可能堆栈的外观。 你可以看到Hello并没有搞乱在Add函数中为c保留的堆栈内存。

你可以通过重写Hello函数来验证

void Hello()
{
  int i = 42;
  printf("Yay - %dn", i);
}

main可以打印42


为了完全理解这一点,我建议你学习你的处理器的程序集,并看看你的代码是如何编译的。 在这一点上,我认为可以帮助,如果我说从函数返回没有调用任何内存释放函数,它只是调整寄存器,因为在添加和打印之间,你没有做任何会改变“释放”堆栈上的值,你得到的号码。 尝试调用一个函数返回.. pfft我不知道77之间(但保存到本地变量!),你会打印一个不同的结果。 尽管学习汇编,做一个合适的程序员。


TL; DR答案,这是未定义的行为。 您无法推理上述执行的任何输出。 如果最终打印出您的手机号码或邮政编码,请不要感到惊讶。 :-)

范围到期后,堆栈位置会发生什么变化,取决于环境。 如果不需要,为c分配的堆栈空间可能不会被重用,因此您会看到假设的正确输出,但仍未定义。 有一天,在不同的环境中,你可能会看到不同的答案。

Mothit Jain先生的回答给出了非常详细的解释。

链接地址: http://www.djcxy.com/p/79905.html

上一篇: Memory allocation stack

下一篇: Use memory on stack