-2

I have to create a matrix with the width and height determined by two parameters obtained from the writing of a file. But, in some cases when the matrix is too big, I've got a segmentation fault. I think is probably because I'm creating the matrix in a static way, so I need to create it dynamically, but is here where my problem appears, because I don't know how to do it. My code right now is this:

    FILE * fp;
    unsigned int width=0;
    unsigned int height=0;
  //Open the file. argv[4] parameter contains the file
  fp=fopen (argv[4],"r"); 
  //Go to the last position which indicates the size
    fseek(fp, 0, SEEK_END); 
  //Return to the start:
    rewind(fp);
  //The value of the first 4 bytes represent the width
    size_t return1 = fread(&width,4,1,fp);
  //The value of the next 4 bytes represent the height
    size_t return2 = fread(&height,4,1,fp);
 //Matrix creation
   if (return1 > 0 && return2 > 0) {
     unsigned int matrix[width][height];
giorgioW
  • 331
  • 5
  • 20

2 Answers2

4

If you are having trouble figuring out how to create arrays dynamically, I would definitely advise you to use the vector class instead.

Vectors are dynamically allocated, and can scale.

std::vector<unsigned int> matrix{width * height};

Notice that I made the vector a single dimension, since it really simplifies a lot when allocating the vector.

To access a specific coordinate you could use:

matrix.at(w * width + h);

Where w and h are the coordinates, h should obviously be in the range 0 <= h < height.

If you were to dynamically allocate your array you would have to use the new operator, and then have to remember to clean up afterwards as well using the proper delete[] operator. There is a better answer for that here on Stack Overflow: How do I declare a 2d array in C++ using new?

Basically it would boil down to:

unsigned int** matrix = new unsigned int*[width];
for (int w = 0; w < width; ++w) {
    matrix[w] = new unsigned int[height];
}

Then you would have to remember to delete the matrix again, using something like this:

for (int w = 0; w < width; ++w) {
    delete [] matrix[w];
}
delete [] matrix;

So, in other words, I recommend that you use the vector class instead.

Of course with sufficiently large values of width and height, even vector can fail, simply because you are trying to allocate too much memory. If that is the case I think you should revisit your design, and reconsider how it is made.

Remember to include the vector header when using vectors:

#include <vector>
Community
  • 1
  • 1
Tommy Andersen
  • 7,165
  • 1
  • 31
  • 50
  • Using vectors and compiling it, I obtain this error: `terminate called after throwing an instance of 'std::out_of_range' what(): vector::_M_range_check: __n (which is 1) >= this->size() (which is 1)` – giorgioW Nov 09 '16 at 11:54
  • @giorgioW what is your input to the function `at` ? – Tommy Andersen Nov 09 '16 at 11:56
  • It's an execution error, sorry. The input is a vector, with `width*height` size called `matrixRed`, like this: `matrixRed.at(i*width+j)=intr;` – giorgioW Nov 09 '16 at 12:02
  • @giorgioW - Note that the index starts at `0`, so if `this->size() == 1` the only possible index is `0` - meaning `i == 0` and `j == 0` in your case. – Bo Persson Nov 09 '16 at 12:03
2
unsigned int matrix[width][height];

This has two problems.

Firstly, width and height are not compile time constants, which is required by the C++ standard for the size of the array. Therefore your program is ill-formed. Your compiler might support variable length arrays (VLA) as a language extension, so it might work with your compiler anyway.

Secondly, VLA may be stored on the stack, and stack space is limited. Indeed, with a large array you can easily overflow the stack. You are correct, that you'll need to allocate the array dynamically. Both because the size is dynamic (assuming you want your program to work with other, standard compliant compilers that do not support VLA) and because it prevents the stack from overflowing.

The simplest way to create a dynamic array is std::vector. Tommy Andersen goes more into depth on how to use vectors in his answer.

eerorika
  • 232,697
  • 12
  • 197
  • 326