pikafan_8080
pikafan_8080

Reputation: 379

malloc() fails to allocate memory inside a function in C

I want to allocate memory dynamically inside a function. The function is named func_1 and is declared as follows:

int func_1(int **destination);

Here destination is a pointer to a pointer. This pointer contains the address of the pointer to which I want to allocate memory dynamically inside the function.

The function func_1 has the following code:

void func_1(int **destination)
{
   *destination = (int*)malloc(sizeof(int) * 10);
   for(int i = 0 ; i < 10 ; i++)
   {
      *destination[i] = i;             //segmentation fault comes HERE
   }    
}

Below is my main() function:

int main()
{
   int *pointer;
   func_1(&pointer);
   return 0;
}

When I try to run this program, I get a segmentation fault (SIGSEGV) error. I used GDB to locate the source of this fault, and it turned out that the line inside the for loop is the culprit for this error.

Please note that I wish to retain the values I have assigned to the dynamically allocated memory inside the function, once the function exits, and that's the reason due to which I have passed the address of the pointer to which I want to allocate memory dynamically.

I want to know:

Thanks for help !

Upvotes: 2

Views: 170

Answers (2)

0x4d45
0x4d45

Reputation: 722

Why am I getting this error ?

You are overwriting the destination pointer instead of assigning the value returned by malloc to the pointer pointed to by the destination pointer.

  • Instead of *destination = (int*)malloc(sizeof(int) * 10) you should type **destination = malloc(sizeof(int) * 10).
  • Instead of *destination[i] = i you should type (**destination)[i] = i.

In C, the array subscript operator [] has a higher precedence than the indirection operator *. In addition to that, the former is left-to-right associative, while the latter is right-to-left associative.

In your case this means that you need to type (**destination)[i] = i; instead of **destination[i] = i, because otherwise the [i] will be evaluated before the ** and you end up indirecting a wild pointer (which will cause a segmentation fault extremely likely in the general and absolutely certainly in this case, since you are referencing a null pointer when i == 0).


How can this be fixed ?

The "just make it work" fix is the one I presented above.

However, that does not address the fundamental issue with your code, which is that it is unnecessarily complicated. Using a pointer to a pointer is very error-prone and should be avoided. Indeed, there is no need to use one at all in this case.

The following does exactly what you want without all the unnecessary complexity:

int* func_1()
{
   int* destination = malloc(sizeof(int) * 10);
   for (int i = 0; i < 10; ++i)
   {
      destination[i] = i;
   }
   return destination;
}
int main()
{
   int* pointer = func_1();
   free(pointer);
   return 0;
}

Please note that I wish to retain the values I have assigned to the dynamically allocated memory inside the function, once the function exits, and that's the reason due to which I have passed the address of the pointer to which I want to allocate memory dynamically.

As I demonstrated above, there is no reason to pass a pointer to the pointer to the function. Memory allocated with malloc is yours to use forever , you just need to keep track of it and release it with a call to free when you no longer need it. How you keep track of the memory doesn't matter - simply returning a pointer is enough in this case. Modifying pointer inside func_1 rather than catching the function's return value provides no additional benefit and only serves to make the code more complicated than it needs to be.


I get the impression that you are somewhat confused about pointers, so I recommend that you revise the subject. Here is a quite clear explanation regarding pointers that also covers pointers to pointeres (and pointers to pointers to pointers): How do pointers work in C?


Read more:

Upvotes: 0

Sergey
Sergey

Reputation: 532

[] (array subscripting) operator has precedence 2

* (dereference) operator has precedence 3

In your code *destination[i] means the same as *(destination[i]). This value is uninitialized and it leads to segmentation fault.

If you will use explicit priority of operation (*destination)[i] you will get the expected result.

void func_1(int **destination)
{
   *destination = (int*)malloc(sizeof(int) * 10);
   for(int i = 0 ; i < 10 ; i++)
   {
      (*destination)[i] = i;             //no segmentation fault
   }    
}

you can read more about precedence here

Full code:

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

void func_1(int **destination)
{
   *destination = (int*)malloc(sizeof(int) * 10);
   for(int i = 0 ; i < 10 ; i++)
   {
      (*destination)[i] = i;             
   }
}

int main()
{
   int *pointer;
   func_1(&pointer);
   return 0;
}

Upvotes: 1

Related Questions