我正在将一个程序从fortran转换为C++。3D数组声明导致段错误
我的代码看上去一切正常,直到我加入这个数组声明:
float TC[100][100][100];
,然后当我运行它,我得到一个分段错误。这个阵列应该只占用8Mb的内存,而我的机器有3Gb。这个声明有问题吗?我的C++很生锈。
我正在将一个程序从fortran转换为C++。3D数组声明导致段错误
我的代码看上去一切正常,直到我加入这个数组声明:
float TC[100][100][100];
,然后当我运行它,我得到一个分段错误。这个阵列应该只占用8Mb的内存,而我的机器有3Gb。这个声明有问题吗?我的C++很生锈。
我猜TC
被分配为一个自动局部变量。这意味着它被存储在堆栈中。你不会得到4mb的堆栈内存,所以会导致堆栈溢出。
要解决该问题,请使用结构化容器或new
的动态分配。
感谢您的帮助!我不需要在Fortran中处理任何这些东西,所以我对此有点无知。 – user1042343
这看起来像一个基于堆栈的声明。尝试从堆中分配(即使用新运算符)。
如果您在函数内部声明它作为局部变量,那么可能是因为堆栈不够大而不适合数组。您可以尝试在堆中分配new
或malloc()
,或者,如果您的设计允许,请将其设置为全局变量。
在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。
谢谢!这有助于很多。 – user1042343
该数组大约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;
}
分割故障通常发生在您尝试访问你不准内存。你确定你没有访问超过你的限制吗? – lvella
该数组实际需要少于4 MB的空间。 –