堆栈段C阵列

时间:2019-02-20 00:13:06

标签: c

我在页面上遇到了一个示例,概述了用C结构表示字符串的各种方法。它解释说,在main外部的函数中定义的数组将存储在堆栈段中,因此在其返回后不一定会存在,可能会导致运行时错误。

引人注目的可能的重复说明了为什么返回数组失败,即将指针推回元素0仍然有效,但没有表明相同存储类别(自动)的原因变量是成功的可以清除堆栈帧的值

“下面的程序可能会打印一些垃圾数据,因为字符串存储在函数getString()的堆栈帧中,并且在getString()返回之后数据可能不存在。”

char *getString() 
{ 
  char str[] = "GfG"; /* Stored in stack segment */

  /* Problem: string may not be present after getSting() returns */
  return str;  
}      
int main() 
{ 
  printf("%s", getString());   
  getchar(); 
  return 0; 
} 

我知道其他局部C变量也将在它们各自的堆栈框架中定义,并且显然可以将它们返回,所以为什么数组有问题?

谢谢

3 个答案:

答案 0 :(得分:5)

这应该大致解释发生了什么,从getString()返回后,其堆栈不再有效。

         ^            ^ 
         |  not valid |    ^            ^
         +------------+    | not valid  |
  str--> | "GfG"      |    | not valid  | <---+
         |  ---       |    | not valid  |     |
         | stack of   |    +------------+     |
         | getString  |    | return(str)| ----+
         +------------+    | ---        |
         |            |    |            |
         | stack of   |    | stack of   |
         | main()     |    | main()     |
         +------------+    +------------+

如果使用gcc -W -Wall编译(应始终使用这些选项),则应给出警告:

warning: function returns address of local variable [-Wreturn-local-addr]

答案 1 :(得分:4)

区别在于返回值与返回指针相反。

执行此操作时:

int f()
{
    int x = 9;
    return x;
}

int main()
{
    int a = f();
    printf("a=%d\n", a);
    return;
}

这是有效的,因为即使x返回时f超出范围,它也是存储在x中的 value (在这种情况下为9)返回。然后将该值分配给a并随后打印。

在您的示例中,您将返回一个数组。在大多数情况下,表达式中使用的数组会衰减为指向其第一个元素的指针。因此return strreturn &str[0]相同。该指针值将返回并传递给printf。然后printf试图取消对该指针的引用,但是它指向的内存(数组str)不再有效。

因此您可以从函数中返回值,但是如果该值是指向局部变量的指针,则它将无效。

答案 2 :(得分:0)

有2种情况:

  1. 当您从本地函数返回一个简单的值,例如intchar时,该变量在该本地函数中定义/声明。它成功完成,因为返回值时会实际复制

  2. 现在在"GfG"中有字符串str,当您执行return str时,复制的值就是str中的值,即阵列的地址位置。因此,在这种情况下,将复制数组位置(指针),而此数组的内容将消失(因为内容在本地堆栈帧上)。