Pointer pointing to another pointer, how to use free () correctly?

When I have a pointer pointing to another pointer like:

int *ponteiro1 = malloc(sizeof(int));
int *ponteiro2;

*ponteiro1 = 5;

ponteiro2 = ponteiro1;
free(ponteiro2);

And I use the free(ponteiro2) command, so am I deallocating the ponteiro1? If yes, should I then do some treatment for ponteiro2?

Author: Maniero, 2020-05-15

2 answers

Let's look at the Code:

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

int main(void) {
    int *ponteiro1 = malloc(sizeof(int));
    *ponteiro1 = 5;
    int *ponteiro2 = ponteiro1;
    printf("%p == %p, %d == %d\n", (void *)ponteiro1, (void *)ponteiro2, *ponteiro1, *ponteiro2);
    free(ponteiro2);
    printf("%p == %p, %d == %d", (void *)ponteiro1, (void *)ponteiro2, *ponteiro1, *ponteiro2);
}

See working on ideone. E no repl.it. also I put on GitHub for future reference .

Then shows that the two variables have the same value, and that value is the pointer. We also see, obviously, that the value contained in the allocated memory is the same when we dereferenciamos the pointer and access the pointed object, after all if it is the same address in the variables then we point certainly for the same object. Nor could it be different, nowhere did the code create 2 objects.

If you consider that free() releases an address from memory when it is released nothing else at that point should be used. In the same way that you allocated only once should release only once. There are no two allocations. Assigning one variable to the other is not creating a new allocation. In C you have to be explicit in everything.

Even if you try to release again you will have a undefined behavior .

It is important to note that the value of the variable is not zeroed, you should not try to access this address after a free().

Some people like to zero the value of the variable to avoid undetected improper access. If you reset and try to access later it will probably break the application which is better to work by coincidence and at another time give wrong result without warning.

If it is not clear, the value of variable that is of type pointer is never the value of the object, there are two completely distinct values in memory, this type always causes a indirection to access the real object.

Zeroing object value

What I found curious is that after the free() the value of the object allocated at this address was considered 0. It gives the impression that the function free() zeroes the value, but this is not to happen. Of course the compiler is free to do whatever it wants, but it would cost and C encourages not to put hidden costs that may not be necessary. In general, simple release will still allow access to the value of the object if nothing overwrites it.

Searching a little it seems that there is case that freeing the application memory can free the memory for the operating system. This occurring address is not released to access by the application. Curiously it does not give error and only accesses a neutral value. I got my hair on my feet because it probably generates some cost. No it means that it is, it may be that there is a change in the value itself, you would have to search its compiler or library to identify what it does.

It may be that it happens only in debug mode , which I do not like the idea because it changes the semantics of the code, it can even hide a bug. It would make more sense because in this mode performance is not a problem, but it seems like a bad solution.

Looking at the source of the allocation may have occurred a means term:

struct malloc_chunk {

  INTERNAL_SIZE_T      prev_size;  /* Size of previous chunk (if free).  */
  INTERNAL_SIZE_T      size;       /* Size in bytes, including overhead. */

  struct malloc_chunk* fd;         /* double links -- used only if free. */
  struct malloc_chunk* bk;

  /* Only used for large blocks: pointer to next larger size.  */
  struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */
  struct malloc_chunk* bk_nextsize;
};

An allocation block may have overwritten the value of the object in this situation. This is not to say that it will always occur, but it happened a case that did not release to the operating system, but had an internal memory management processing that used the memory inside the free().

Then I keep thinking that even printf() could, in theory, have done something that overwritten the value while it was processing the print. I do not think good and I believe to be less likely. I don't remember this function doing an allocation in the heap.

 4
Author: Maniero, 2020-06-11 14:45:34

When doing ponteiro2 = ponteiro1, ponteiro2 you're not pointing to ponteiro1, but you're sharing the same memory address since you're assigning it the value of ponteiro1 which is that memory address.

So the value of *ponteiro2 is also the same 5 that you assigned to that memory address when doing *ponteiro1 = 5.

By doing free (ponteiro2), you are releasing the memory address shared by the two pointers. Right now, both ponteiro1 and ponteiro2 are pointing to a address that is no longer reserved for them.

Now when trying to access *ponteiro1 or *ponteiro2, the error of Segmentation fault will occur - "error that occurs when a program tries to access (for reading or writing) an address in RAM that is reserved for another program (or the operating system itself) or that does not exist."

Answer: you no longer need to do anything to ponteiro1 or ponteiro2, unless you want to do ponteiro1 = NULL and ponteiro2 = NULL if you want to use the variables again later.

 2
Author: Maf, 2020-05-15 11:34:19