3D 数组声明导致分段错误 [重复]

3d array declaration causes segmentation fault [duplicate]

提问人:user1042343 提问时间:11/12/2011 更新时间:11/12/2011 访问量:2482

问:

我正在将程序从 fortran 转换为 C++。

我的代码似乎运行良好,直到我添加此数组声明:

 float TC[100][100][100];

然后当我运行它时,我收到分段错误错误。这个阵列应该只占用 8Mb 的内存,而我的机器有 3 GB。这个声明有问题吗?我的 c++ 很生疏。

C++语言

评论

1赞 lvella 11/12/2011
分段错误通常发生在您尝试访问不允许访问的内存时。您确定您没有超出阵列的限制进行访问吗?
0赞 David Alber 11/12/2011
该数组实际上需要不到 4 MB 的空间。

答:

3赞 tenfour 11/12/2011 #1

我猜被分配为自动局部变量。这意味着它被存储在堆栈上。您没有获得 4mb 的堆栈内存,因此会导致堆栈溢出。TC

要解决此问题,请使用带有结构化容器的动态分配或 .new

评论

0赞 user1042343 11/17/2011
感谢您的帮助!我不必在Fortran中处理任何这些东西,所以我对此有点无知。
0赞 Throwback1986 11/12/2011 #2

这看起来像一个基于堆栈的声明。尝试从堆中分配(即使用 new 运算符)。

0赞 lvella 11/12/2011 #3

如果你在函数内部将其声明为局部变量,则可能是你的堆栈不够大,无法容纳数组。您可以尝试在堆中分配 with 或 ,或者,如果您的设计允许,请将其设置为全局变量。newmalloc()

0赞 Mooing Duck 11/12/2011 #4

在 C++ 中,堆栈的空间有限。MSVC 默认此大小为 1MB。如果堆栈使用超过 1MB,它将段错误或堆栈溢出或其他东西。您必须将该结构移动到动态内存中。要将其移动到动态内存,您需要如下内容:

typedef float (bigarray)[100][100][100];
bigarray& TC() {
    static bigarray* ptr = NULL;
    if (ptr == NULL) {
        ptr = new float[100][100][100];
        for(int j=0; j<100; j++) {
            ptr[j] = new float[100][100];
            for(int i=0; i<100; i++)
                ptr[j][i] = new float[100];
        }
    }
    return *ptr;
}

这将在第一次访问动态内存时将结构分配为锯齿状数组。您可以从矩形数组中获得更高的性能,但必须更改类型:

typedef std::vector<std::array<std::array<float, 100>, 100> bigarray;
bigarray TC(100);

根据 http://cs.nyu.edu/exact/core/doc/stackOverflow.txt,gcc/linux 默认堆栈大小为 8MB,这对于您的结构来说还不够大,如果您真的愿意,MSVC 具有将堆栈大小增加到 32MB 的标志。Linux 有一个命令可以将堆栈大小增加到 32MB。int main()ulimit

评论

0赞 user1042343 11/17/2011
谢谢!这很有帮助。
3赞 celtschk 11/12/2011 #5

该阵列大约有 4 MB 大。如果此定义位于函数内部(作为局部变量),则编译器会尝试将其存储在堆栈上,而堆栈在大多数系统上无法增长那么大。

Fortran 编译器可能静态分配它(除非明确标记为递归,否则不允许递归调用 Fortran 例程,因此局部变量的静态分配适用于非递归函数),因此不会发生错误。

一个简单的解决方法是显式声明变量 static,假设 Fortran 函数未声明递归。但是,如果您尝试从修订后的版本递归调用该函数,这可能会在以后咬您一口。因此,更好的解决方案可能是动态分配它。但是,这会花费额外的时间,因此取决于代码的性质,可能会对性能造成太大影响(Fortran 代码通常是性能很重要的数字代码)。

如果选择将数组设置为静态数组,则可以内置针对意外递归调用的保护:

void yourfunction()
{
  static bool active;
  static float TC[100][100][100];

  assert(!active);
  active = true;

  // your code

  active = false;
}