内存分配堆栈
在堆栈中,存储器被保留用于main
我们称之为堆栈帧main
功能。
当我们调用Add
函数时,内存保留在堆栈顶部。 在Add
函数堆栈框架中, a
和b
是局部指针, c
是一个计算总和的整数,然后返回参考。 c
是Add
函数的局部变量。
现在,当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
变量,在函数调用之后访问c
是undefined-behavior
并且可能会打印预期结果,或者可能会做出意想不到的事情。
虽然C
没有强制执行,但通常使用堆栈实现。 出于性能原因,当函数返回时,它会保持堆栈区不变。 这就是你看到值5
即1+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下一篇: Use memory on stack