How can I allocate memory and return it (via a pointer-parameter) to the calling function?

a_m0d picture a_m0d · Sep 9, 2009 · Viewed 49.4k times · Source

I have some code in a couple of different functions that looks something like this:

void someFunction (int *data) {
  data = (int *) malloc (sizeof (data));
}

void useData (int *data) {
  printf ("%p", data);
}

int main () {
  int *data = NULL;

  someFunction (data);

  useData (data);

  return 0;
}

someFunction () and useData () are defined in separate modules (*.c files).

The problem is that, while malloc works fine, and the allocated memory is usable in someFunction, the same memory is not available once the function has returned.

An example run of the program can be seen here, with output showing the various memory addresses.

Can someone please explain to me what I am doing wrong here, and how I can get this code to work?


EDIT: So it seems like I need to use double pointers to do this - how would I go about doing the same thing when I actually need to use double pointers? So e.g. data is

int **data = NULL; //used for 2D array

Do I then need to use triple pointers in function calls?

Answer

Martin B picture Martin B · Sep 9, 2009

You want to use a pointer-to-pointer:

void someFunction (int **data) {
  *data = malloc (sizeof (int));
}

void useData (int *data) {
  printf ("%p", data);
}

int main () {
  int *data = NULL;

  someFunction (&data);

  useData (data);

  return 0;
}

Why? Well, you want to change your pointer data in the main function. In C, if you want to change something that's passed in as a parameter (and have that change show up in the caller's version), you have to pass in a pointer to whatever you want to change. In this case, that "something you want to change" is a pointer -- so to be able to change that pointer, you have to use a pointer-to-pointer...

Note that on top of your main problem, there was another bug in the code: sizeof(data) gives you the number of bytes required to store the pointer (4 bytes on a 32-bit OS or 8 bytes on a 64-bit OS), whereas you really want the number of bytes required to store what the pointer points to (an int, i.e. 4 bytes on most OSes). Because typically sizeof(int *)>=sizeof(int), this probably wouldn't have caused a problem, but it's something to be aware of. I've corrected this in the code above.

Here are some useful questions on pointers-to-pointers:

How do pointer to pointers work in C?

Uses for multiple levels of pointer dereferences?