views:

139

answers:

3
+2  Q: 

Pointer question

Okay I go through 2 layers of functions fun1 calls func2 calls func3 . I pass a pointer all the way down using basically int *ptr, at the lowest "level" of the call stack I also have another function that dynamically allocates memory for an int array. At the top level (func1 level) I always get null back for the passed pointer. I have traced down to func3 and the allocated memory is being filled with values, but as the call stack unwinds func3 -> func2 suddenly the pointer just goes away (0x0000_0000)? I don't understand at func3 level I basically say ptr = allocate_ptr_array, but from that return it goes to NULL! Even though I didn't free the memory, what in the world is going on? I know my question is confusing. I have watched this happen in the debugger though

+6  A: 

The pointer is basically passed by value. You need to pass pointer to pointer (int **p) to get the memory allocated back in outer function.

function1(int *p)
{
 p = //allocate memory using malloc
}

function2(int **p)
{
 *p = //allocate memory using malloc
}

function3()
{
 int *p;
 function1(p); 
// in this case pointer is passed by value. 
//The memory allocated will not be available in p after the function call function1.

int **p;
function2(&p); 
//in this case pointer to pointer p has been passed.
// P will have the memory allocated even after 
//the function call function1
}

}

aJ
you mean i can't have this ? func1(void) { int *ptr; func2(int* ptr); //just showing type style)}func2(int *ptr) { func3(int *ptr); }func3(int *ptr) { do_some_work_on_malloced_array; ptr = }You mean one of those will get deleted as the calls unwind? it's in func2 where I notice ptr go to NULL. i thought you can pass it right up the calls?
It is not deleted. The address to memory allocated in func3 will not be available in outer function. its a memory leak basically.
aJ
You can do one more thing. make func3 return int* instead of taking as a parameter. In outer function add int *p = func3(); This will make sure that u get the pointer to the memory allocated in inner function
aJ
+2  A: 

To illuminate aJ's (completely correct) answer with some code:

void func1(void)
{
    int *int_array;

    func2(&int_array);

    /* Some stuff using int_array[0] etc */

    /* ... */

    free(int_array);
}

void func2(int **a)
{
     /* ... stuff ... */

     func3(a);

     /* .... stuff ... */
}

void func3(int **a)
{
    (*a) = malloc(N * sizeof **a);
}
caf
so basically I need a pointer to a pointer all the way down because it was allocated at the bottom layer? This is sort of new stuff to me, usually I'm allocating in say func1 and then just passing down that "array" along with the size. Sorry pointers always throw me!
Yes, because you want the bottom level to update the value of a variable that exists at the top level - so you need to pass down a pointer to that variable. It just so happens that the variable in this case is already a pointer, so you end up passing a pointer-to-a-pointer. An alternative is to make your lower functions return the new pointer value, and explicitly assign the return value to int_array at the top level. That's how the standard library functions tend to work.
caf
only problem is i actually have two arrays to return :( so i have to do it through params. thanks!
If the arrays are related to each other then you could wrap two pointers in a structure and return that.
caf
A: 

Here is a good example for future reference bye other people. It makes sense after implementation and thanks to these guys.

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

void func3(int **ptr)
{
    int i;
    (*ptr) = (int *)malloc(25*sizeof(int));

    for (i=0; i < 25; i++) (**ptr) = i;
    printf("func3: %d\n",ptr);
}

void func2(int **ptr)
{
    func3(ptr);
    printf("func2: %d\n", ptr);
}
void func1(void)
{
    int *ptr;
    printf("ptr before: %d\n", ptr);
    func2(&ptr);
    printf("ptr after: %d\n", ptr);
}

void func4(int **ptr)
{
    static int stuff[25];
    printf("stuff: %d\n",stuff);
    *ptr = stuff;
}

int main(void)
{
    int *painter;
    func1();
    func4(&painter);
    printf("painter: %d\n", painter);
    return 0;
}