微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c – 内存分配堆栈

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

当我们调用Add函数时,内存保留在堆栈顶部.在Add函数堆栈帧中,a和b是局部指针,c是一个计算总和的整数,然后我们返回引用. c是Add函数的局部变量.

现在当Add函数执行完成时,堆栈中的内存空间也被释放,所以当我们尝试使用指针p访问main中的这个地址时,我们试图访问的内容基本上是一个释放空间.编译器发出警告,但为什么它仍然正确打印值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是未定义的行为并且可能打印预期结果,或者可能做一些意外的事情.

虽然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 - %d\n",i);
}

可以在主要打印42.

原文地址:https://www.jb51.cc/c/110711.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐