-1

Let's say I have a function which accepts a pointer to a struct, which is defined like so

typedef struct Array {
    int capacity;
    int size;
    void **items;
} Array;

This function will realloc the memory of array->items to increase the size.

The function is given below

void doubleArray(Array *array) {
    array->capacity *= 2;
    void **items = realloc(array->items, array->capacity);
    if(items == NULL) {
        exit(1);
    }
    array->items = items;
}

What I am have difficulty understanding is, if I assign void **items to the result of realloc, and realloc returns a new memory address because the previous buffer has been overwritten, does array->items get assigned correctly to the new value even after returning from the function?

Or will the fact that void **items is defined within the local scope of the function doubleArray mean that array->items becomes a dangling pointer because it is not correctly re-assigned because the reference to void **items is deleted once the function exits?

random_coder_101
  • 1,782
  • 3
  • 24
  • 50
  • 1
    Possible duplicate of [How \`realloc\` work actually in the background?](https://stackoverflow.com/questions/21437482/how-realloc-work-actually-in-the-background) – Abhineet Feb 13 '18 at 08:40
  • @Abhineet - Not sure its a duplicate.. The question you posted talks about how `realloc` works, whereas my question is an extension of that regarding what happens to the pointer reference defined in the function that `realloc`'s return value is assigned to. Correct me if I'm wrong though. – random_coder_101 Feb 13 '18 at 08:43
  • The `realloc` won't work anyway because the size passed is incorrect. You have passed the number of elements and ignored the size of each. – Weather Vane Feb 13 '18 at 08:48
  • @WeatherVane - Do you mind elaborating on that? I'm not really following – random_coder_101 Feb 13 '18 at 08:48
  • If there are `capacity` elements they will need more than 1 byte each. They will each need the size of a pointer. – Weather Vane Feb 13 '18 at 08:49
  • 1
    So I suggest `void **items = realloc(array->items, array->capacity * sizeof *items);`. However it seems strange that the `struct` contains `void **items;` as this can't be doubly-dereferenced. – Weather Vane Feb 13 '18 at 08:57
  • @WeatherVane - Would I need to do this even if `array->capacity` is an `int` and I am assigning only `int` values to `void **items`? I recognize I'm making this more complex than it needs to be, but just want to make sure I understand why this works. – random_coder_101 Feb 13 '18 at 09:11
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/165029/discussion-between-random-coder-101-and-weather-vane). – random_coder_101 Feb 13 '18 at 09:12

2 Answers2

3

Your problem of understanding is not about realloc(), its's about pointer and local variable in general.

does array->items get assigned correctly to the new value even after returning from the function?

In your code above, it is correctly assigned. Although pointer points to some address, pointer itself is an ordinary variable.

array->items becomes a dangling pointer because it is not correctly re-assigned because the reference to void **items is deleted once the function exits?

No. No pointer is deleted. Local variable void **items itself is out of scope, but not what it points to.

Consider:

void foo(Array *a) {
    int sz = 23;
    a->size = sz;
}

Will a->size become "dangling" after the function return ? Your problem is the same as this one.

llllllllll
  • 16,169
  • 4
  • 31
  • 54
0

The first thing that you should note is, the expression:

void **items = realloc(array->items, array->capacity);

should probably be changed to:

void **items = realloc(array->items, (array->capacity) * sizeof(void *));

Secondly, to answer your question:

does array->items get assigned correctly to the new value even after returning from the function?

Its does, because you pass a pointer (to a structure) to your function, thus the function has the ability to modify the struct member items.

Next, when you assign array->items = items; and the function returns, the local variable items runs out of scope, but remember, its value which have been assigned to array->items, is the address of memory that has allocated storage duration, so array->items is not a dangling pointer because it is pointing to valid memory.

machine_1
  • 4,266
  • 2
  • 21
  • 42