0

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;
}
Demetry Pascal
  • 383
  • 4
  • 15
  • 3
    parameters are passed by value unless you pass them by reference. Pointers are no exception to this. Your `init_matrices` does not init `A`, `B` or `C` from `main` – 463035818_is_not_an_ai Mar 31 '21 at 18:38
  • Beneficial reading: [C++ FAQ - Matrix](https://www.google.com/search?q=C%2B%2B+FAQ+matrix&rlz=1C1GCEB_enUS935US935&oq=C%2B%2B+FAQ+matrix&aqs=chrome..69i57.5509j0j7&sourceid=chrome&ie=UTF-8) – Thomas Matthews Mar 31 '21 at 18:38
  • 1
    You are assigning to a local copy of your pointer arguments with your `new` statements in your function. You need to assign to the pointer the variable is pointing to. In `main`, the variable `A` is not pointing to allocated memory so you get a segfault when you try to access it. – jkb Mar 31 '21 at 18:40
  • Turn on and **pay attention to** all of your compiler warnings – Woodford Mar 31 '21 at 18:40
  • Try with `*A = new double *[a_rows];` – Ripi2 Mar 31 '21 at 18:42
  • 1
    [Maybe this can help?](https://stackoverflow.com/questions/21943621/how-to-create-a-contiguous-2d-array-in-c/21944048#21944048) – PaulMcKenzie Mar 31 '21 at 18:43
  • thank u @largest_prime_is_463035818 but how can I do necessary logic to edit arrays in functions and returning them to next step? – Demetry Pascal Mar 31 '21 at 18:44
  • 1
    Does this answer your question? https://stackoverflow.com/questions/373419/whats-the-difference-between-passing-by-reference-vs-passing-by-value (well not the "how to make a 2d array" question, but "why does my init_matrices not work correctly?") – 463035818_is_not_an_ai Mar 31 '21 at 18:44
  • you can pass them by reference, but actually I'd rather suggest to start from scratch with what others pointed you to. Use a 1D array and pretend it to be 2D, thats what you need to do anyhow, memory isnt two dimensional, and 1D + index transformations is soo much easier than 2D arrays – 463035818_is_not_an_ai Mar 31 '21 at 18:46
  • @largest_prime_is_463035818 I know but I shall use 2D matrixes as 2pointer array, not 1D array or vectors So can u show how can I modify and return arrays like ``` double** arr; func1(arr); // modify array func2(arr); // use modified array ``` – Demetry Pascal Mar 31 '21 at 18:49
  • @PaulMcKenzie good way but I need to use these array in other functions later so it doesn't help me – Demetry Pascal Mar 31 '21 at 18:55
  • @Ripi2 compilation error – Demetry Pascal Mar 31 '21 at 18:55
  • 1
    @ДмитрийПасько -- I don't understand your comment that you need to "use these arrays in other functions". Just pass them as parameters. The example program I showed you shows how to create the array -- after that, you do whatever you want with them. – PaulMcKenzie Mar 31 '21 at 20:37

1 Answers1

2

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.

user4581301
  • 33,082
  • 7
  • 33
  • 54