2011-11-11 95 views
2

我正在将一个程序从fortran转换为C++。3D数组声明导致段错误

我的代码看上去一切正常,直到我加入这个数组声明:

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

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

+1

分割故障通常发生在您尝试访问你不准内存。你确定你没有访问超过你的限制吗? – lvella

+0

该数组实际需要少于4 MB的空间。 –

回答

3

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

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

+0

感谢您的帮助!我不需要在Fortran中处理任何这些东西,所以我对此有点无知。 – user1042343

0

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

0

如果您在函数内部声明它作为局部变量,那么可能是因为堆栈不够大而不适合数组。您可以尝试在堆中分配newmalloc(),或者,如果您的设计允许,请将其设置为全局变量。

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。

+0

谢谢!这有助于很多。 – user1042343

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