【问题标题】:Stack frame memory allocation堆栈帧内存分配
【发布时间】:2014-10-26 19:15:34
【问题描述】:

就像每个函数都放在一个堆栈帧上执行,并在完成后刷新。因此,任何局部变量都不能用于其他函数。但是我们如何才能将局部变量返回给调用者呢?

int pickMin( int x, int y, int z ) {
 int min = x ;
 if ( y < min )
    min = y ;
 if ( z < min )
    min = z ;
 return min ;   }

上面的代码工作正常。然而,在下面的代码中,编译器确实给出了一条警告消息——“warning: function returns address of local variable [-Wreturn-local-addr] return a;”,但它在最后打印了一个垃圾值,我认为这很好,因为变量已经被刷新了。但是为什么在 ABOVE 程序中没有发生这种情况?!我的意思是,它也应该返回一个垃圾值。此外,我知道下面代码中的问题可以使用malloc 解决,然后返回该值。 :)

int *returnarray(){
 int a[10]; int i;
  for(i=0;i<10;++i){
     a[i] = i;
 }return a;}   

【问题讨论】:

  • 请修正你的缩进。

标签: c stack


【解决方案1】:

return 语句正是这样:它复制变量的值,并将其留在堆栈顶部,以便调用函数可以使用它。现在,在 C 中,这适用于简单值,而不适用于数组,因为您的“数组变量”a 实际上只是其第一个值的地址。

【讨论】:

    【解决方案2】:

    在第一种情况下,您返回变量的值。

    虽然,在第二种情况下,您返回一个局部变量的地址,正如您正确所说的那样,该地址不适用于其他函数。在 C 中,数组的名称是该数组的基地址。因此,在第二种情况下,“数组的基址”被复制到任何变量/指针,该变量/指针被分配了该函数的返回值

    【讨论】:

      【解决方案3】:

      首先,仔细阅读call stack wikipage。上面有漂亮的图片。另请参阅x86 calling conventions wikipage。

      然后,(某些 C 函数的)结果通常在返回时通过一个寄存器(或者,对于较大的 struct-s,在调用者分配的堆栈空间中)。

      详情以ABI 为准。对于 x86-64(64 位)上的 Linux,x86-64 ABI 提到了 %rax 寄存器以返回结果(在常见情况下,但当结果很大时,struct 调用者会为其传递一个地址)。

      顺便说一句,原则上,我相信 C99 标准中没有任何内容需要堆栈,但我不知道没有调用堆栈的 C 实现(通常是处理器堆栈,即通过 stack register) .

      【讨论】:

        【解决方案4】:

        C 通过值传递所有内容。在您的第一个 sn-p 中,return min 返回一个 int 变量。它的值被返回。第二个 sn-p 由return 和一个数组名组成,该数组名衰减为一个指针。
        返回的局部变量的内存地址。但是,存在此变量的函数已返回,并且访问此函数使用的内存会调用未定义的行为。

        处理这种情况(即:需要返回一个数组)的方法是将目标数组作为参数传递给函数,或者使用malloc分配内存并返回该指针。
        堆内存有点慢,更容易出错,但需要你照顾它。尽管如此,here's an example of both approaches
        create_fill 分配、分配并返回指向堆内存的指针,fill_array 不返回任何内容,但希望您传递一个数组(衰减为一个指针)和一个最大值要填充的长度。优点是:堆栈内存不需要太多关注,并且会胜过堆。

        【讨论】:

          猜你喜欢
          • 2018-07-24
          • 2011-05-28
          • 1970-01-01
          • 2015-12-18
          • 2019-05-17
          • 2011-10-09
          • 2021-11-18
          • 2021-04-08
          相关资源
          最近更新 更多