1

I need to create a dynamic array which is than populated by a function. I have no way to know in advance how big is that array. So I did the following:

TAB_TYPE *column_types = malloc(100*sizeof(TAB_TYPE));
hExtract = make_table_definition(jsstr, tokens, column_types);

I randomly decided to allocate 100 elements. Inside the function I resized it with:

realloc(column_types, tokens[0].size /2 * sizeof(TAB_TYPE)))

The above line yielded the following error when compiling with GCC:

error: ignoring return value of ‘realloc’, declared with attribute warn_unused_result  

Which I managed to by pass like this:

if (!(int *) realloc(column_types, tokens[0].size /2 * sizeof(TAB_TYPE)))
    log_die("Failed to allocate memory to column_types!");

log_die is existing with message to stderr.

I also tried the following approach, which yields segmentation fault:

 //first declare a NULL pointer:
 TAB_TYPE *column_types = NULL; 

 //inside the function
TAB_TYPE *t = realloc(column_types, tokens[0].size /2 * sizeof(TAB_TYPE));
if (!t){
    log_die("Failed to allocate memory to column_types!");
}else{
    column_types = t ;
}

// outside the function
for (int i=0; i < tokens[0].size / 2; i++ )
    printf("Type %d : %d\n", i, column_types[i]); -> SEGMENTATION FAULT!!!

My questions are two:

  1. Is this the way to do it?
  2. Why does the second approach end with segmentation fault?
oz123
  • 27,559
  • 27
  • 125
  • 187
  • You need to assign the result of `realloc()` back to the array variable. And if you're doing it in a function, you either have to return the pointer from the function, or pass a pointer to a pointer as an argument so you can update it. – Barmar Dec 11 '14 at 08:04
  • Why don't you simply allocate it inside the function and then return it to the caller? What's the purpose of all this unnecessary complication of allocating 100 elements and then reallocating inside the function? Obviously, the caller is going to need the size of the array, but you can return that as well (in an output argument). The cleanest solution would probably be to implement a function that does nothing but computing the required size. Then, do the allocation and initialization (array filling), in the caller function. – barak manos Dec 11 '14 at 08:12
  • Read the documentation for `realloc` instead of using casts to hide warnings – M.M Dec 11 '14 at 08:16

2 Answers2

4

When you realloc, you are again creating memory. You need to reassign that memory to your pointer. But when you pass a pointer to a function, you can change the values which is pointed to by that pointer but not the pointer itself. For this you have 2 options

  1. Return the realloced pointer and assign it to initial pointer
  2. Pass your pointer as pointer to pointer.

This explains it better

How do I modify a pointer that has been passed into a function in C?

Community
  • 1
  • 1
Pankaj Bansal
  • 889
  • 1
  • 12
  • 37
0

Point 1:

C uses pass-by-value for function parameter passing. To alter the memory allocation of column_types from some other function, you need to pass a pointer to column types.

To clarify, if after allocating memory you pass the column_types to some other function, you'll be able to change the value pointed by that memory location [*column_types], not the pointer [column_types] itself.

Point 2:

TAB_TYPE *t = realloc(column_types, tokens[0].size /2 * sizeof(TAB_TYPE));

realloc() will resize the existing memory size of column_types, and will return a pointer to the newly allocated memory , which is collected in t, and it will free() the existing allocation. You should return t from the function and assign the return value to a TAB_TYPE pointer.

From the man page of realloc()

void *realloc(void *ptr, size_t size);

and

The realloc() function returns a pointer to the newly allocated memory, which is suitably aligned for any kind of variable and may be different from ptr,

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261