【问题标题】:Where is local variable allocated? Heap or stack?局部变量分配在哪里?堆还是栈?
【发布时间】:2013-01-10 02:03:11
【问题描述】:

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);
}

编译运行后没有报错。但是当我去注释 //fun(s) ,然后 SIGSEGV 被抓住了。谁能告诉我为什么?

【问题讨论】:

  • 答案就在标题中……
  • 您的机器上没有 16 TB 的虚拟内存吗?

标签: c memory segmentation-fault heap-memory stack-memory


【解决方案1】:

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

这个页面说局部变量和传递的参数是在堆栈上分配的

没错。

但是当我去注释 //fun(s) ,然后 SIGSEGV 被捕获。谁能告诉我为什么?

堆栈上的内存比堆上的内存更有限¹。您在堆栈上分配 2000000x2000000 数组,然后将其传递给函数。这很可能会超出可用的堆栈空间,从而导致分段错误。

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

¹尽管在这种情况下并没有什么不同,因为正如 slugonamission 指出的那样,该数组占用了 16TB,因此也会超过堆上的可用内存。

【讨论】:

  • 在 32 位系统上也称为 16TB (2000000x2000000x4),在 64 位系统上也称为 32TB。很明显,这会导致堆栈崩溃。
  • 在 32 位和 64 位机器上都是 16 TB;如果机器使用 16 位 int,它可能只有 8 TB。
  • 函数调用被注释掉时,变量未被使用,被编译器淘汰。当它被传递给函数时,......好吧,所有的地狱都崩溃了。
【解决方案2】:

此外,这是一个很好的例子,为什么您只是按值传递函数参数,而通常您通过引用传递参数:

#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);
}

我认为它根本不会运行,因为它需要 4TB 的堆栈内存。并且它在您的代码中使用//fun(s) 顺利编译和运行,因为编译器转储了未使用的s 变量并且根本没有在运行时声明。

【讨论】:

    猜你喜欢
    • 2010-10-26
    • 1970-01-01
    • 2010-11-15
    • 2016-09-08
    • 2012-11-23
    • 1970-01-01
    • 2010-11-09
    • 1970-01-01
    相关资源
    最近更新 更多