3
char *oldPointer, *newPointer;

oldPointer = (char*)malloc(1000);
newPointer = (char*)realloc(oldPointer, 2000)

Can oldPointer be used now?

What happens now?

oldPointer = newPointer;

What happens if free(newPointer)?

Begench
  • 33
  • 4
  • You seem to be conflating the pointer itself and the allocated memory it points to. Yes, `oldPointer` can be used after the `realloc()`, but you should check that `newPointer` isn't `NULL` or you'll have a memory leak. Same with `oldPointer = newPointer` -- totally fine, but if the `realloc()` failed, you'll have a memory leak. – torstenvl Mar 30 '19 at 04:30
  • As for `free(newPointer)`: if `realloc()` failed, then `newPointer` is `NULL` and your call to `free()` will have no effect; if `realloc()` succeeded, then `free()` will have the expected effect and both pointers will now point to unallocated space and you should not dereference them. – torstenvl Mar 30 '19 at 04:36
  • 1
    NO need to cast `void`-pointers (which `malloc()` & Friends return) in C. – alk Mar 30 '19 at 06:25

4 Answers4

2

What happens when 2 pointers point to same area and 1 of them is freed?

oldPointer = (char*)malloc(1000);
newPointer = (char*)realloc(oldPointer, 2000)

oldPointer and newPointer might not point to the same area. This is what realloc() does. The new pointer might be different if the memory manager decides to do so (for instance if the old area does not have enough space to cover the new required space). Assuming they do point to the same area induces an undefined behavior (UB - may or not may not work as you expect, leading to a difficult debugging).

1 of them is freed

After

oldPointer = (char*)malloc(1000);
newPointer = (char*)realloc(oldPointer, 2000)

You cannot use oldPointer after that realloc. Only newPointer exists. If you free oldPointer and the address changed, UB (crash likely). If you free oldPointer and it was the same address as newPointer, this is the same as freeing newPointer, of course.

Anyway, the rule is simple: do not use oldPointer after it's be realloc'ed. Unless

oldPointer = malloc(1000);
oldPointer = realloc(oldPointer, 2000);
^^^

you use the same pointer. But is not advised as if the realloc fails you have no trace of the previously allocated address (unless you saved it) ; it's a leak.

And don't cast malloc / realloc.

Support Ukraine
  • 42,271
  • 4
  • 38
  • 63
Déjà vu
  • 28,223
  • 6
  • 72
  • 100
1

You cannot safely use either pointer before checking what happened after realloc().

Possibility 1:

realloc failed, then newpointer will be NULL and cannot be used, but oldPointer can.

Possibility 2:

realloc succeded and did not have to relocate the old malloc'd memory. In that case you can use both pointers. (They hold the same address value)

Possibility 3:

realloc succeded but had to allocate memory at a different place and free the old block of memory. Now oldPointer will still point at the old memory address, which is not valid anymore. This is known as a dangling pointer.

However, newPointer is valid and can be used.

GermanNerd
  • 643
  • 5
  • 12
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/190994/discussion-on-answer-by-germannerd-what-happens-when-2-pointers-point-to-same-ar). – Samuel Liew Mar 31 '19 at 21:58
0

Can oldPointer be used now?

When you say "be used" I assume that you mean "can the pointer be dereferenced". In other words - is it ok to do *oldPointer or oldPointer[200] or something similar.

The answer is: It depends on the value of newPointer.

The function realloc will return a pointer to the memory after reallocation unless an allocation error occur (e.g. out of memory). If an error occur realloc returns NULL.

Therefore the correct way of using realloc is to save the return value in another pointer and then check for NULL. Like

oldPointer = (char*)malloc(1000);                // BTW: dont use cast
newPointer = (char*)realloc(oldPointer, 2000);   // BTW: dont use cast
if (newPointer == NULL)
{
    // realloc failed....

    // the value of oldPointer is still valid

    // It is ok to dereference oldPointer, e.g. using oldPointer[10]

    // Here you will normally have some error handling
}
else
{
    // realloc success

    // the value of oldPointer shall be considered invalid.
    // the value of oldPointer may NOT be dereferenced anymore.
    // also notice that you may NOT call free(oldPointer).

    // Normally we save the value of newPointer into oldPointer
    // so that the value of oldPointer becomes valid and usable again
    oldPointer = newPointer;
}

What happens if free(newPointer)?

If newPointer points to the same memory as oldPointer it will no longer be allowed to dereference any of the pointers. Example:

oldPointer = newPointer;
free(newPointer);
oldPointer[9] = something;  // Illegal !!
newPointer[9] = something;  // Illegal !!
Support Ukraine
  • 42,271
  • 4
  • 38
  • 63
  • >>// the value of oldPointer may NOT be dereferenced anymore<< It *should* not be dereferenced, but C allows for it. This is why such a (possibly) dangling pointer is so dangerous, as most likely the memory freed by realloc will still hold the old data for a while, and errors will manifest themselfs only much later, or maybe even never unless run in a different setup. – GermanNerd Mar 30 '19 at 05:42
  • @GermanNerd No, C do **not** allow it. C defines it as "undefined behavior". Compilers allow it because it is too difficult (actually impossible) for the compiler to detect illegal dereferences. – Support Ukraine Mar 30 '19 at 05:46
  • C does allow it - that is why we have 'undefined behaviour' in the first place. It is the very definition of UB. – GermanNerd Mar 30 '19 at 05:47
  • @GermanNerd That must be your own home made definition of undefined behavior – Support Ukraine Mar 30 '19 at 05:49
  • 3.4.3 1 undefined behavior behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard **imposes no requirements.** My emphasis. So any construct that is syntactically translatable is legal. However, there is no definition what the results of such code will be, and in the end comes down to the compiler's implementation. Or, in other words, UB is code that is **outside of the language definition**, but not **illegal**. – GermanNerd Mar 30 '19 at 06:36
0

Per the the standard:

The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by the calloc, malloc, or realloc function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.

levengli
  • 1,091
  • 7
  • 18