18

I am getting an segmentation fault when I pass the double pointers to the function to initialize the memory

int main()
{
    double **A;
    initialize(A, 10, 10);
 ......
}

void initialize(double **A, int r, int c)
{
   A = (double **)malloc(sizeof(double *)*r);
   for(int i = 0; i< r; i++) {
        A[i] = (double *)malloc(sizeof(double) *c);
        for(int j = 0; j < c; j++) {
            A[i][j] = 0.0;
        }
   }
}

How can I pass the double pointers to the functions.....

veda
  • 6,416
  • 15
  • 58
  • 78

5 Answers5

23

Like others have said, you need to take a pointer to pointer to pointer in your init function. This is how the initialize function changes:

void initialize(double ***A, int r, int c)
{
   *A = (double **)malloc(sizeof(double *)*r);
   for(int i = 0; i< r; i++) {
        (*A)[i] = (double *)malloc(sizeof(double) *c);
        for(int j = 0; j < c; j++) {
            (*A)[i][j] = 0.0;
        }
   }
}

And main will be:

int main()
{
    double **A;
    initialize(&A, 10, 10);
}

Also, the code as you posted it should cause no segmentation fault when passing the A pointer in. The segmentation fault most likely occurs when you return from the function and try to access A, because the A in main will not have been initialized. Only a copy of it is initialized the way you do it, and that copy is local to the initialize function, so it's lost when you return.

IVlad
  • 43,099
  • 13
  • 111
  • 179
  • @LVlad Hi, nice answer. Just revisiting my C: if you want to modify a pointer in C, you need to pass a pointer to a pointer. If you need to modify a pointer to a pointer, you need to pass a pointer to a pointer to a pointer. Why? So can we say, if we want to modify a value, we also need to pass a pointer to that value? Please explain more. Thanks in advance. – Unheilig Jan 07 '14 at 21:37
  • HI Unheilig, this is related to call by reference. For example (some type) *A then If there is need to modify some type at place other than where A is currently defined, you'll have to pass address of A and will require derefrencing the passed address in called function. The reason for passing address is that called function gets it's separate stack in process address space. In problem above, A defined in main() is in separate stack and is never accessed by initialize(). There is nothing wrong reported if A is not accessed back in main(). – Vishal Sahu Mar 11 '16 at 16:45
  • Thank you so much, I'm struggling with it for 3 days. – Hari Kiran Vusirikala Jun 22 '17 at 13:28
20

If you want to modify a pointer to pointer you need to pass a pointer to pointer to pointer.

void func(double ***data) { *data = malloc(sizeof(double*)*10); for.... };
double ** data; func(&data);
Šimon Tóth
  • 35,456
  • 20
  • 106
  • 151
  • 2
    Just revisiting my C: if you want to modify a pointer in C, you need to pass a pointer to a pointer. If you need to modify a pointer to a pointer, you need to pass a pointer to a pointer to a pointer. Why? So can we say, if we want to modify a value, we also need to pass a pointer to that value? Please explain more. Thanks in advance. – Unheilig Jan 07 '14 at 21:38
  • To sum this up, one can say that if you want to modify a value inside a function, you need to pass the pointer to that value to the function. Values are (always) just copied (by value) to functions. [Example/Reference](https://stackoverflow.com/questions/2229498/passing-by-reference-in-c) – j3141592653589793238 Mar 03 '19 at 17:52
2

Well for one thing, the A inside initialize is a copy of the A in main -- so when you get back to main, its A is still uninitialized. If you try and use it -- boom!

To pass it to initialize 'by reference', you need to change the parameter type to double*** and pass in &A in main. Then, when you use it in initialize, you need to dereference it each time, i.e. *A.

Stuart Golodetz
  • 20,238
  • 4
  • 51
  • 80
1
  1. You are not checking for out of memory errors. Fail.

  2. You pass BY VALUE an uninitialized value A to initialize() and then initialize that. But back in main(), that local variable A is still uninitialized. Instead you might have initialize() return the double** (e.g. A = initialize(...)) or modify initialize() so its first formal parameter is a double ***pA that you initialize with *pA = (double**)malloc(...);

Jan Gray
  • 3,454
  • 19
  • 15
  • Re. (1), fair point, but how many toy programs like this have ever run out of memory? – Stuart Golodetz Dec 02 '10 at 19:59
  • Well, do you want to counsel beginners to check for out of memory conditions or do you want them to learn to write fragile software?No. If he wants A to be initialized as an out parameter of initialize(), he needs to pass in a double***, which is then used as (*pA) wherever A appeared in the original – Jan Gray Dec 02 '10 at 20:27
1

This is the kind of thing you do not want to do. Instead of unnecessarily using an out argument for this, allocate in the function and return the result. Do this instead:

int main() 
{
    double **A;
    A = initialize(A10, 10);
}

double** initialize(int r, int c)
{
   double **A;
   A = malloc(sizeof(double *)*r);
   for(int i = 0; i< r; i++) {
        A[i] = (double *)malloc(sizeof(double) *c);
        for(int j = 0; j < c; j++) {
            A[i][j] = 0.0;
        }
   }
  return A;
}
arsenm
  • 2,903
  • 1
  • 23
  • 23