为什么这个数组分配会导致段错误?

时间:2015-09-01 03:07:26

标签: c++ segmentation-fault

我正在尝试创建一组int的向量,但我在这段代码中遇到了段错误。

int main() {
    vector<int> x[1000000];
}

我认为这是因为我超过了堆栈大小,所以我使用了动态分配,它似乎解决了问题。但是,为什么这样做:

vector<int> x[1000000];

int main() {
    // do nothing
}

这个工作?

int main() {
    static vector<int> x[1000000];
}

1 个答案:

答案 0 :(得分:2)

这是因为在第一个示例中,数组是在堆栈上分配的,并且您的实现对可用堆栈施加了太严格的限制。你的第二个例子可能是纯粹的运气。

关于程序内存的正常布局,请参阅this picture,访问白色区域可能会导致分段错误(无论如何都是个坏主意)。

现在,当您分配一个非静态局部变量时,直接数据将在堆栈上分配,但构造函数也可以通过new在堆上分配空间。在你的情况下,构造函数也可能会分配内存(vector的直接数据可能与指针一样少,但你分配了一百万个,因此至少有8Mb的直接数据)。可能是构造函数的存在实际上使得程序段错误成为堆栈上分配的空间,否则可能是未被访问的(当您实际访问堆栈限制之外的空间时,您将获得段错误。)

当您分配静态或全局数据时,直接数据将分配在数据或BSS段中,如果预发布数据(即构造函数运行之前的数据,如果有)为零,则它将被置于BSS段中。在您的情况下,数据可能会被放置在BSS中。

现在请注意,使用全局分配时,构造函数将在到达main之前运行(而不是在第一次调用函数之前不会运行的静态),但是您可以通过new动态分配在构造函数中并且在main之前调用new意味着未定义的行为,你应该认为自己很幸运,第二个例子没有失败(它可以在没有事先通知的情况下这样做)。

从中学到的教训是,只有在不需要复杂的构造函数时,才能将大数据放在全局范围内。如果您需要复杂的构造函数,最好通过new动态分配它。您当然可以将其放在本地static中,如果全局需要,则返回对该对象的引用。