c 中每个函数都有自己的堆栈吗?

Mos*_*man 4 c stack-overflow gcc

我最近了解了堆栈,因此我正在尝试了解堆栈大小是多少以及溢出时会发生什么。我发现在 Unix 上默认堆栈大小为 8 MiB,这支持了我的发现,因为我无法在函数中声明大小大于或等于 8 MiB 的字符串main。但是,当我在其中声明变量时,main()它会影响其他函数。例如:

#include <stdio.h>

void foo(void)
{
    long int size = 1024*1024*2;
    char str[size];
    str[size - 1] = 'a';
    printf("%c\n", str[size - 1]);
}

int main(int argc, char** argv)
{
    long int size = 1024*1024*6;
    char str[size];
    str[size - 1] = 'a';
    printf("%c\n", str[size - 1]);
    foo();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

此代码会导致分段错误,但如果我将字符串大小设置为 5 MiB,main()则不会出现分段错误。这是否意味着我的 C 程序无法为局部变量(所有函数)分配超过 8 MiB 的 RAM?如果是这样,堆栈的意义何在?

Abh*_*ate 6

不,每个函数没有自己独立的堆栈空间。您的程序中只有一个堆栈,并且可供您使用的堆栈空间是有限的

\n

堆栈的工作原理

\n
\n

这种后进先出的行为正是函数返回调用它的函数时所做的事情。

\n
\n

堆栈中的流程

\n
    \n
  1. 调用者将返回地址压入堆栈
  2. \n
  3. 当被调用函数完成执行时,它将从调用堆栈中弹出返回地址(此弹出元素也称为堆栈)并将控制权转移到该地址。
  4. \n
  5. 如果被调用函数调用另一个函数,它将把另一个返回地址推到同一调用堆栈的顶部,依此类推,信息按照程序的指示进行堆叠和出栈。
  6. \n
\n

上述所有过程都发生在同一个堆栈内存中。每个函数在堆栈中都有自己的空间,但每个函数都在同一个堆栈中分配其空间。这称为程序的全局调用堆栈。\n它用于存储函数内部使用的局部变量。

\n

然而,动态分配的空间存储在堆上。堆用于存储动态变量。它是 process\xe2\x80\x99 内存的一个区域。malloc(), calloc(),resize()所有这些内置函数通常用于存储动态变量。

\n

至于堆栈溢出问题,调用堆栈的大小是有限的。只能使用一定量的内存。如果发生许多函数调用,堆栈空间最终会耗尽,这将给您带来堆栈溢出错误,这很可能导致程序崩溃

\n

如果你的函数中有很多变量或者程序中某些变量需要大量的空间,那么堆栈空间最终会耗尽,从而导致堆栈溢出。例如,在大多数情况下,以下内容可能会导致堆栈溢出并导致程序崩溃:

\n
int main() {\n   int A[100000][100000];\n}\n
Run Code Online (Sandbox Code Playgroud)\n

希望这能消除您的疑虑!

\n

笔记

\n

在多线程环境中,每个线程分别获得自己的调用堆栈空间,而不是具有相同的全局调用堆栈。因此,在多线程环境中,您的问题的答案将是YES

\n