局部变量在哪里分配?堆还是堆?

CDT*_*CDT 6 c memory heap stack segmentation-fault

http://www-ee.eng.hawaii.edu/~tep/EE160/Book/chap14/subsection2.1.1.8.html 此页面说明传递的局部变量和参数是在堆栈上分配的,所以我试过:

#include <stdio.h>
#include <stdlib.h>
#define A 2000000
#define B 2

typedef struct {
    int a[A][A];
} st;

void fun(st s){}

void main()
{
    st s;
    //fun(s);
}
Run Code Online (Sandbox Code Playgroud)

编译和运行后没有报告错误.但是当我取消注释时//fun(s),然后SIGSEGV被抓住了.有谁能说出原因?

sep*_*p2k 11

局部变量在哪里分配?堆还是堆?

该页面表示传递的局部变量和参数在堆栈上分配

究竟.

但是,当我取消注释// fun(s)时,然后SIGSEGV被捕获.有谁能说出原因?

堆栈上的内存比堆上的内存要多得多.您在堆栈上分配2000000x2000000数组,然后将其传递给函数.这很可能超过可用的堆栈空间,从而导致分段错误.

至于为什么在函数调用被注释掉时不会发生分段错误.首先,正如Jonathan Leffer所指出的那样,编译器可能会s完全优化掉,因为它没有被使用.但即使它没有,你可能也不会得到段错误,因为在堆栈上分配内存只是意味着增加堆栈指针.在大多数实现中,它本身永远不会导致分段错误.只有在您尝试访问已分配的内存并且系统意识到您超出了堆栈的边界(并且在整个内存的情况下)时,才会发生分段错误.

¹虽然在这种情况下没有什么区别,因为正如slugonamission指出的那样,数组占用16TB,因此也会超过堆上的可用内存.

  • 它在32位和64位机器上都是16 TB; 如果机器使用16位`int`,它可能只有8 TB. (5认同)
  • 在32位系统上也称为16TB(2000000x2000000x4),在64位系统上称为32TB.很明显,这会导致堆栈崩溃. (3认同)
  • 当函数调用被注释掉时,变量未被使用,并被编译器消除.当它被传递给函数时,......好吧,所有的地狱都破裂了. (3认同)