Home > OS >  Segmentation fault when trying to read a file with 4000^2 characters
Segmentation fault when trying to read a file with 4000^2 characters

Time:02-28

I'm writing a program to read numbers from a .txt file to then put into a 2-dimensional matrix that I can use to do matrix multiplication with but at this point I'm having alot of trouble getting the portion of my code that scans the file to work properly. I have two randomly generated matrixes that I'm using and for the smaller one it will read the first 400 values but then the rest of the array will be zeros. For the larger one, which is 4000x4000, it will just throw a segmentation fault without even going into the main. Any ideas at what would be causing this? I change ARRAY_SIZE to whatever the array length and Width are.

#include <stdio.h>
#include <stdlib.h>

#define ARRAY_SIZE 4000

int main(int argc, char *argv[]) {

// Form to read: ./programname #ofthreads inputfilename1 inputefilename2 outputfilename
if(argc != 5) {
   printf("Error! usage: ./programname #ofthreads inputfilename1 inputfilename2 outputfilename");
   return (EXIT_FAILURE);
}

// get number of threads
   int numThreads = atoi(argv[1]);


// make file pointers
   FILE *fp1;
   FILE *fp2;

// assign pointer to file name

   fp1 = fopen(argv[2], "r");
   fp2 = fopen(argv[3], "r");


   // Error Handling if file doesn't exist
   if (fp1 == NULL) {
       printf("Error: File 1 does not exist. ");
       return (EXIT_FAILURE);
   }
   if (fp2 == NULL) {
       printf("Error: File 2 does not exist. ");
       return (EXIT_FAILURE);
   }

// initialize arrays
   int array1[ARRAY_SIZE][ARRAY_SIZE] = {0};
   int array2[ARRAY_SIZE][ARRAY_SIZE] = {0};


// initialize dimension ints
int size1[2];
int size2[2];

// Get Dimensions
fscanf(fp1,"%d ",&size1[0]);
fscanf(fp1,"%d \n", &size1[1]);
fscanf(fp2,"%d ",&size2[0]);
fscanf(fp2,"%d \n", &size2[1]);

   int length1 = size1[0];
   int width1 = size1[1];
   int length2 = size2[0];
   int width2 = size2[1];

   for(int n = 0; n < length1; n  ){
       for(int m = 0; m < width1; m  ){

           fscanf(fp1, "%d ", &array1[m][n]);
       }
   }

   for(int n = 0; n < length2; n  ){
       for(int m = 0; m < width2; m  ){
           fscanf(fp1, "%d ", &array2[m][n]);
       }
   }

   // Process file here




   // Close file
   fclose(fp1);
   fclose(fp2);

   for(int n = 0; n < width1; n  ){
       for(int m = 0; m < length1; m  ){
         //  printf("%d ", array1[m][n]);
       }
       printf("\n");
   }

printf("Number of threads = %d\n", numThreads);
printf("Size1 = %d x %d\n", size1[0],size1[1]);
printf("Size2 = %d x %d\n", size2[0],size2[1]);

   return 0;
}

CodePudding user response:

Process stack size is limited (few MiBs). It varies between systems based on OS implementation. If you need anything over that, better get it from heap (Memory management calls).

int rows = 4000;
int cols = 4000;
int **array = (int**) malloc (rows * sizeof(int*));
if (!array) {
    perror("malloc1");
    exit(1);
}
for (ri = 0; ri < rows;   ri) {
    array[ri] = (int*) malloc (cols * sizeof(int));
    if (!array[ri]) {
        perror("malloc2");
        exit(2);
    }
}

Remember to free the allocated memory in reverse order. First the columns' (loop) then the rows'.

Edit: Assuming you allocated both array1 & array2 using malloc() calls.

Reading array2 contents

fscanf(fp1, "%d ", &array2[m][n]);

shouldn't that be fp2?

CodePudding user response:

2 x 4000 x 4000 ints will most probably take up more stack space than you have available. Allocate the memory dynamically using calloc instead (declared in stdlib.h):

// allocate space for ARRAY_SIZE elements of size int[ARRAY_SIZE] and zero the memory:
int(*array1)[ARRAY_SIZE] = calloc(ARRAY_SIZE, sizeof *array1);
int(*array2)[ARRAY_SIZE] = calloc(ARRAY_SIZE, sizeof *array2);
if(array1 == NULL || array2 == NULL) exit(1);

However, by the looks of it, you don't actually need all that memory in most cases since you get length1, width1, length2 and width2 from the files. Allocate the arrays after you've gotten that input from the files:

if(fscanf(fp1, " %d %d", &length1, &width1) != 2 ||
   fscanf(fp2, " %d %d", &length2, &width2) != 2) exit(1);

int(*array1)[width1] = calloc(length1, sizeof *array1);
int(*array2)[width2] = calloc(length2, sizeof *array2);

if(array1 == NULL || array2 == NULL) exit(1);

Then use array1 and array2 just like you did before.

When you are done with them, free the allocated memory:

free(array1);
free(array2);
  • Related