内存分配栈

Memory allocation stack

在栈中,内存是为main预留的,我们称之为main函数的栈帧。

当我们调用Add函数时,内存被保留在栈顶。在Add函数栈帧中,ab是局部指针,c是一个计算和的整数,然后我们return引用。 cAdd 函数的局部变量。

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

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

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;
}

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

作用域过期后,堆栈位置发生的变化取决于环境。如果不需要,分配给 c 的堆栈 space 可能不会被重用,因此您会看到 assumed proper 输出,但仍然 未定义。总有一天,在不同的环境中,你可能会看到不同的答案。

Mr. Mothit Jain's 对此给出了非常详细的解释。

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

虽然C没有强制要求,但通常它是使用堆栈实现的。出于性能原因,当函数 returns 时,它保持堆栈区域不变。这就是您看到值 51+4 的原因。但你永远不应该指望这个。


当您使用第二个函数时,行为仍未定义,因此您可以获得任何输出。实际上,如果您在第二个函数中定义另一个变量并使用它,输出可能会改变。

                       +-----------------+
                       .(local variables).
                       |'''''''''''''''''|
                       |                 |
+----------------+     . PRINTF FUNCTION .
|  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 - %d\n", i);
}

可以在main中打印42

为了完全理解这一点,我建议您为您的处理器学习汇编,看看您的代码是如何编译的。在这一点上,我认为如果我说从函数返回不调用任何内存释放函数,它只是调整寄存器并且因为在添加和打印之间你没有做任何会改变 "deallocated" 上的值的事情,我认为会有帮助堆栈,你得到的数字。尝试调用一个 returns.. pfft 我不知道 77 之间的函数(但请将其保存到局部变量!),您将打印出不同的结果。学会汇编,做个合格的程序员

Hello 函数不会将任何新内容放入堆栈,因为它没有自动变量。因此之前被 c 占用的内存位置仍然没有改变。更改 Hello 以便它修改内存,您将更改 p 处的值。

void Hello(void)
{
    //This will overwrite the memory previously containing '5' with '3`, the number
    //of characters output by the printf() function.
    int grub = printf("Yay");
}

我想是因为你没有在Hello函数中定义"stack variable",当我运行下面的程序时:

#include <stdio.h>

void Hello()
{
  int tt = 100;
  int tt1 = 5000;
  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;
}

它在我的 Linux 中打印 5000 并且在我的 Mac 中打印 1,无论如何我认为它们是两者都出乎意料。