3d数组声明导致分段错误

时间:2011-11-11 19:27:04

标签: c++

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

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

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

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

5 个答案:

答案 0 :(得分:3)

我猜测TC被分配为自动局部变量。这意味着它存储在堆栈中。你没有得到4mb的堆栈内存,所以它导致堆栈溢出。

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

答案 1 :(得分:3)

该数组大约4兆字节。如果这个定义在一个函数内(作为局部变量),那么编译器会尝试将它存储在堆栈上,而在大多数系统上都不会那么大。

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

一个简单的修复方法是显式声明变量static,假设Fortran函数没有声明递归。但是,如果你试图从修订版本中递归调用该函数,这可能会让你迟到。因此,更好的解决方案可能是动态分配它。然而,这需要额外的时间,因此取决于代码的性质,可能会对您的性能造成太大影响(Fortran代码通常是性能很重要的数字代码)。

如果您选择将数组设置为静态,则可以建立防止意外递归调用的保护:

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

  assert(!active);
  active = true;

  // your code

  active = false;
}

答案 2 :(得分:0)

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

答案 3 :(得分:0)

如果你在函数内部声明它作为局部变量,那么堆栈可能不足以适合数组。您可以尝试使用newmalloc()在堆中进行分配,或者,如果您的设计允许,则将其设置为全局变量。

答案 4 :(得分:0)

在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,这对于你的结构来说还不够大 int main()如果你真的想要,那么MSVC有标志,以增加堆栈大小高达32MB。 Linux有一个ulimit命令可以将堆栈大小增加到32MB。