Search code examples
c++arrayspointerssegmentation-faultdynamic-arrays

Segmentation fault error with 2D arrays C++


I dunno why I have segmentation error when I'm trying to set or get any element from created array!!

Here it is in line with A[0][0] = 1;

I'm using g++ 9.3.0. What do I do wrong?

#include <iostream>

#define SIMULATIONS 30

using namespace std;

void init_matrixes(int a_rows, int b_cols, int vec_len, double **A, double **B, double **C)
{

    A = new double *[a_rows];
    B = new double *[vec_len];
    C = new double *[a_rows];

    for (int i = 0; i < a_rows; i++)
    {
        A[i] = new double[vec_len];
        C[i] = new double[b_cols];
    }
    for (int i = 0; i < vec_len; i++)
        B[i] = new double[b_cols];

}


int main()
{

    double s;
    int t1, t2, a_rows, b_cols, vec_len;
    
    for (auto v : {50, 100})
    {

        a_rows = v;
        b_cols = v;
        vec_len = v;

        for (int i = 0; i < SIMULATIONS; i++)
        {
            double **A, **B, **C;
            init_matrixes(a_rows, b_cols, vec_len, A, B, C);
            
            A[0][0] = 1; // error here

        }
        std::cout << "size = " << v<< "  time = " << s / SIMULATIONS << endl;
    }

    return 0;
}

Solution

  • TL;DR version

    Use std::vector or a matrix class like the one described here. This will eliminate the need for special allocation and deallocation functions thanks to the magic of RAII.

    What went wrong?

    A pointer is just another variable, but one that can contain the location of another object. Like any other variable, the pointer will be will be passed by value into a function and copied by default. The object pointed at is passed by reference (by way of pointer), but the pointer itself is passed by value.

    double **A defines A as a pointer to a pointer to a double that is a copy of the pointer provided by the caller.

    A = new double *[a_rows];
    

    updates the copy and the caller is none-the-wiser. As a result all of the memory allocated is leaked at the end of the function because the local A goes out of scope.

    So How do I fix it?

    Pass the pointers by reference.

    void init_matrixes(int a_rows, 
                       int b_cols, 
                       int vec_len, 
                       double ** & A, 
                       double ** & B, 
                       double ** & C)
    

    A, B, and C, are passed by reference (references this time) and are no longer copies.

    A = new double *[a_rows];
    

    Updates the pointer provided by the caller, and the caller now has a pointer pointing to valid storage.