简体   繁体   中英

Segmentation fault while trying to declare a 5D array in a C Program

I am converting a program from fortran77 to C Programming Language, In the fortran program a 5D array is declared as shown below, and the code compiles and executes well. But when I convert the same code to C with the same values, the C code compiles but it gives Segmentation fault.

If this issue is because of the different standard layout of multidimensional arrays memory allocation between the two languages, I have tried all dimension combinations while declaring the array in C, and in all cases it also gives a 'Segmentation fault'.

I have also tired the 'calloc' technique shown below, and it works but I don't know how to assign values to the globally declared array.

Note: The segmentation fault is at the declaration step (ie The program stops there)

So basically my questions are: - Why does it works in fortran but not in C ?, and, - How to solve this issues in 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;
                              ^

The stack size in C and also in C++ is very limited, generally, a 1D-array of maximum 1e5 size is allowed, and if we assume "double" size as 8 bytes then that translates into maximum memory of 8*1e5 bytes.

Now, let's look at your 5D-array, it's trying to allocate 10*38*20*20*20 = 3,040,000 "double" units which when converted into the memory is 24,320,000 bytes which is well above the allotted stack size in C or C++. That's why you are getting a SEG-FAULT.

You can try initializing the array globally that way it is allocated heap memory which is typically bigger than the stack memory, even then the max size is limited to 8*7*1e5 bytes at max(depends on your machine).

You solve it by creating the array on the heap instead of the stack.

double* dNdpt = malloc(sizeof(double)*nID*i2maxbin*imaxbin*imaxbin*imaxbin);

then keep track of where you are in this gigantic array by calculating the index

a simpler example :

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;

the following proposed code:

  1. places the array in file scope rather than on the stack
  2. cleanly compiles
  3. avoids the use of dynamic memory allocation/free'ing
  4. cleanly runs and exits without crashing
  5. avoids using VLAs

And now the proposed code:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM