每个函数在c中都有自己的堆栈吗?
我最近了解了堆栈,所以我正在试验看看堆栈的大小,以及当它溢出时会发生什么。我发现在Unix上,默认堆栈大小是8 MiB,这支持我的发现,因为我无法在我的每个函数在c中都有自己的堆栈吗?,c,gcc,stack-overflow,C,Gcc,Stack Overflow,我最近了解了堆栈,所以我正在试验看看堆栈的大小,以及当它溢出时会发生什么。我发现在Unix上,默认堆栈大小是8 MiB,这支持我的发现,因为我无法在我的main函数中声明大小大于或等于8 MiB的字符串。但是,当我在main()中声明变量时,它会影响其他函数。例如: #include <stdio.h> void foo(void) { long int size = 1024*1024*2; char str[size]; str[size - 1] =
main
函数中声明大小大于或等于8 MiB的字符串。但是,当我在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;
}
#包括
无效foo(无效)
{
长整数大小=1024*1024*2;
字符str[size];
str[size-1]=“a”;
printf(“%c\n”,str[size-1]);
}
int main(int argc,字符**argv)
{
长整数大小=1024*1024*6;
字符str[size];
str[size-1]=“a”;
printf(“%c\n”,str[size-1]);
foo();
返回0;
}
此代码导致分段错误,但如果我在
main()
中设置字符串大小为5 MiB,则不存在分段错误。这是否意味着我的C程序不能为局部变量(所有函数)分配超过8MIB的RAM?如果是这样,堆栈的意义是什么?不,每个函数都没有自己独立的堆栈空间。您的程序中只有一个堆栈,并且可用的堆栈空间有限
堆栈的工作原理
这种后进先出行为正是函数返回时所做的
调用它的函数
堆栈中的流
malloc()
,calloc()
,resize()
所有这些内置函数通常用于存储动态变量
至于堆栈溢出问题,调用堆栈大小是有限的。只能使用一定量的内存。如果发生许多函数调用,堆栈空间最终将耗尽,这将导致堆栈溢出错误,这很可能导致程序崩溃
如果函数中有很多变量,或者程序中有一些变量需要很大的空间,那么堆栈空间最终会耗尽,并导致堆栈溢出。例如,在大多数情况下,以下情况可能会导致堆栈溢出,并导致程序崩溃:
int main() {
int A[100000][100000];
}
希望这能消除你的疑虑
注意:
在多线程环境中,每个线程分别获得自己的调用堆栈空间,而不是拥有相同的全局调用堆栈。因此,在多线程环境中,您的问题的答案将是是堆栈是一个,内存中有共享空间,每个嵌套函数调用都会“推”一个新的“框架”(局部变量的空间集)到该共享堆栈上。是的,内存中堆栈空间的总大小在(当前)正在执行的所有函数之间共享,如果程序运行期间使用的总空间超过操作系统为其预留的空间,则会导致(ahem)“堆栈溢出”崩溃
关键是为每个函数的调用提供工作空间。通常,堆栈上任何特定函数使用的空间量都非常小——可能是一些整数或几个小数组,等等。想想几十或几百字节,通常不是千字节,当然也不是兆字节。这主要是惯用的,当您使用了足够多的自己和他人的代码时,您会习惯于在堆栈上有意义的东西和没有意义的东西。在生产代码中,将兆字节作为实际的局部变量是非常不寻常的
实际上,在现实世界中,堆栈溢出错误的主要原因是偶然的无限递归——当您在没有递归基本情况下反复调用相同的函数时。这些堆栈帧可能每个都很小,但如果调用链是无界的,最终会溢出
当您想要使用实际较大的内存块、较大的字符串缓冲区等时,通常会从称为“堆”的不同共享内存块中分配它们。您可以分配(与
malloc
及其近亲一起)您需要的内容,然后在完成后分配free
。堆的内存空间对于您的程序来说是全局的,并且不受特定函数调用的约束或关联 C语言标准对堆栈一无所知。函数的调用方式、参数的传递方式以及自动存储对象的存储位置取决于实现
大多数实现实际上只有一个堆栈,但我将给出一些非常常见的示例