我正在将程序从fortran77转换为C编程语言,在fortran程序中声明了一个5D数组,如下所示,并且代码编译和执行良好。但是当我将相同的代码转换为具有相同值的 C 时,C 代码会编译,但它会给出分段错误。
如果这个问题是由于两种语言之间的多维数组内存分配的标准布局不同,我已经尝试了所有维度组合,同时用 C 声明数组,并且在所有情况下它都会给出"分段错误"。
我也厌倦了下面显示的"calloc"技术,它有效,但我不知道如何将值分配给全局声明的数组。
注意:分段错误在声明步骤(即程序停止到此(
所以基本上我的问题是:- 为什么它在 fortran 中有效,但在 C 中不起作用?,并且,- 如何在C中解决此问题?
! Fortran77 Code
parameter (i2maxbin=38)
parameter (imaxbin=20)
parameter (Nid=10)
real*8 dNdpt(Nid,i2maxbin,imaxbin,imaxbin,imaxbin)
/* C Code */
const int i2maxbin = 38;
const int imaxbin = 20;
const int nID = 10;
double dNdpt[nID][i2maxbin][imaxbin][imaxbin][imaxbin];
/* Declaring using calloc */
double (*dNdpt)[nID][i2maxbin][imaxbin][imaxbin][imaxbin] =
calloc(sizeof(*dNdpt), 38);
for(int i = 0; i < nID; i++)
{
for(int j = 0; j < i2maxbin; j++)
{
dNdpt[i][j][0][0][0] = 12.22673423;
}
}
When executing it gives me this error
error: assignment to expression with array type
dNdpt[i][j][0][0][0] = 12.22673423;
^
以下建议的代码:
- 将数组放在文件范围内而不是堆栈上
- 干净地编译
- 避免使用动态内存分配/释放
- 干净利落地运行和退出而不会崩溃
- 避免使用 VLA
现在建议的代码:
#define i2maxbin 38
#define imaxbin 20
#define nID 10
double dNptr[nID][i2maxbin][imaxbin][imaxbin][imaxbin];
int main( void )
{
for(int i = 0; i < nID; i++)
{
for(int j = 0; j < i2maxbin; j++)
{
dNptr[i][j][0][0][0] = 12.22673423;
}
}
}
C 和 C++ 中的堆栈大小非常有限,通常,允许最大 1e5 大小的 1D 数组,如果我们假设"双倍"大小为 8 字节,那么这意味着最大内存为 8*1e5 字节。
现在,让我们看一下您的 5D 数组,它试图分配 10*38*20*20*20 = 3,040,000 个"双"单位,当转换为内存时为 24,320,000 字节,远高于 C 或 C++ 中分配的堆栈大小。这就是为什么你得到一个SEG错误。
您可以尝试全局初始化数组,以便为其分配堆内存,该堆内存通常大于堆栈内存,即使这样,最大大小也限制为 8*7*1e5 字节(取决于您的计算机(。
堆而不是堆栈上创建数组来解决它。
double* dNdpt = malloc(sizeof(double)*nID*i2maxbin*imaxbin*imaxbin*imaxbin);
然后通过计算索引来跟踪您在这个巨大数组中的位置
一个更简单的例子:
double* my2dim = malloc(sizeof(double)*10*20); // 10 rows 20 cols
my2dim[3][2] = 10.0 would be written *(my2dim + 3 * 20 + 2) = 10.0;