0

I met an error, Segmentation fault. I want to know why this error occurred to me.

Question: Can this error occurred from reckless computation that my computer cannot handle?

When I used the matrix with structure (4094, 30, 50), I met the Segmentation fault. But, When I used the matrix (4094, 4, 50) did not show any error at all.

There is a detailed story below.

I made a C program to read and write a three-dimensional text file processed from Fortran90 program.

The text file that I want to read is written from the Fortran90 program below:

DO X= 1, 4094
DO Y= 1, 30
             WRITE(24,*) (MATRIX(X,Y,Z), Z=1,50)
END DO
END DO

So, I thought I wrote a three-dimensional matrix with this structure, X x Y x Z (4094 x 30 x 50), in a text file.

I checked its structure with bash code: wc -l.

wc -l [filename].txt
149220

This means that the number of values in X x Y in the text file. I thought my Fortran90 program wrote the matrix with my intention well .

After that, I made a C program that read and write the text file.

#include <stdio.h>

#define x 4094
#define y 5
#define z 30

int main()
{
    int i, j, k;
    int state_r, state_w;
    double signal [z][y][x];
    
    FILE *fp_r;
    FILE *fp_w; 

    fp_r=fopen("/[filename].txt", "r");
    fp_w=fopen("/[filename].txt", "w");

    if(fp_r==NULL){
       puts("fail to open a file to read!");
       return -1;
                  }

    if(fp_w==NULL){
       ptus("fail to open a file to write!");
       return -1;
                  }
 
//read
    for(k=0;k<z;k++){
    for(j=0;j<z;j++){
    for(i=0;i<z;i++){
                      
                      fscanf(fp_r,"%lf",%signal[k][j][i];
                    }
                    }
                    }

//write
    for(k=0;k<z;k++){
    for(j=0;j<z;j++){
    for(i=0;i<z;i++){
                      
                     fprintf(fp_w,"%lf",%signal[k][j][i];
                    }
                     fprintf(fp_w,"\n");
                    }
                    }

    state_r=fclose(fp_r);
    if(state_r !=0){
                    printf("error occurred while removing stream");
                    return 1;
                   }
    
    state_w=fclose(fp_w);
    if(state_w !=0){
                    printf("error occurred while removing stream");
                    return 1;
                    }

    return 0;
}                          

If your answer is "no", then, how can I solve this problem?

In fact, I am reading this matrix with the structure (4094, 30, 30) with python3 program. Thus, I cannot understand why C program cannot cope with this structure!

  • 1
    I suspect the array may be *too large* to allocate on the stack. The failing case is ~50MB (assuming double = 8 bytes) and the succeeding case is ~6.5MB. Try with malloc *or* mark the array with the static storage modifier. – user2864740 Jan 24 '22 at 06:46
  • 1
    https://stackoverflow.com/a/1825996/2864740 , https://stackoverflow.com/q/27481707/2864740 (for stack limits and “behavior” when such is exceeded); https://stackoverflow.com/a/14753177/2864740 (discussion of static modifier in such a case); https://stackoverflow.com/q/13504807/2864740 (generally covers “maximum size”). While there may be other issues (didn’t look, don’t care), I’d first ensure the stack isn’t being trivially exploded. – user2864740 Jan 24 '22 at 06:50
  • An easy experiment would be to change the doubles into floats and run again – Serve Laurijssen Jan 24 '22 at 07:08
  • @ServeLaurijssen **Good suggestion**. I tried with floats. The program worked by (4094, 8, 50). But, **I need more!** My goal is (4096, 30, 512). How can I increase the performance of my program? – Changwan Sun Jan 24 '22 at 07:22
  • Please read the links.. switching to float would still not work at ~25MB for the original size reported to fail. The default stack size is usually 8MB on Linux systems (note the working size reported was ~6.5MB).. – user2864740 Jan 24 '22 at 07:39
  • Also, it does not appear that the entire array needs to be loaded at once, making doing so an overall *waste of resources*. (4096, 30, 512) x 8 ~ 500MB (still 250MB with 4 byte floats). – user2864740 Jan 24 '22 at 07:43
  • 1
    Did you try `double signal [z][y][x];` -> `static double signal [z][y][x];` ? – Jabberwocky Jan 24 '22 at 07:47
  • Please use tag [tag:fortran] for all Fortran questions. You also do not just tag the question c89 or c99 but [tag:c]. – Vladimir F Героям слава Jan 24 '22 at 09:10
  • @VladimirF, although this question isn't really a Fortran question, is it? – francescalus Jan 24 '22 at 09:32
  • @francescalus No, this question could do quite well without any Fortran tag, I realized that after re-reading it after reading the answer. – Vladimir F Героям слава Jan 24 '22 at 10:08
  • @VladimirF, Thanks for your comment. I will ask better later! – Changwan Sun Jan 24 '22 at 12:32
  • @Jabberwocky Great!, it worked! I can read and write the text file with original size! Could you explain in detail about what the problem was in my code? Also, Why does **static** enable my program to read bigger matrix? – Changwan Sun Jan 24 '22 at 12:36
  • @Jabberwocky But, I came home and used my slower notebook to execute this program. It failed: Segmentation fault(core dumped). **static** does not work in the slow computer. Then, I have to try an answer suggested. – Changwan Sun Jan 24 '22 at 13:58
  • @ChangwanSun without the `static`, the variable is a local variable, and the total size of local variables is usually rather limited. The second comment covers this. With `static`, the variable is like a global variable and it is stored elsewhere in memory where the size is much less limited. Your C learning material should cover this. – Jabberwocky Jan 24 '22 at 14:21
  • @ChangwanSun But I have no idea why the code fails on the other computer, but I guess you were still running the old version of your program. – Jabberwocky Jan 24 '22 at 14:22
  • @user2864740 Thank you for your useful links. [link](https://stackoverflow.com/questions/27481707/maximum-stack-size-for-c-c-program) is great! I was able to understand that the size of the stack depends on the linker and It's impossible to measure is size. – Changwan Sun Jan 25 '22 at 00:17
  • @Jabberwocky Yes. My bad. I used the previous version of my program! Thanks a million! – Changwan Sun Jan 27 '22 at 15:46

1 Answers1

0

So as it is a stack issue you need to allocate the array on the heap.

double ***signal = malloc(z * sizeof(double **));
for (int i = 0; i < z; i++)
{
  signal[i] = malloc(y * sizeof(double *));
  for (int j = 0; j < y; j++)
  {
    signal[j] = malloc(x * sizeof (double));
  }
}

Now you can use the same indexing as if it was an array on the stack

Serve Laurijssen
  • 9,266
  • 5
  • 45
  • 98