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

Asked

Viewed 70 times

4

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 command free(ponteiro2), then I’m dislocating the ponteiro1? If so, I should then do some treatment for the ponteiro2?

2 answers

4


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);
}

Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.

It 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 slip the pointer and access the pointed object, after all if it is the same address in the variables then we point certainly to the same object. Nor could it be different, nowhere did the code create 2 objects.

If you consider that free() releases a memory address when it is released nothing else at that point should be used. In the same way that you allocated only once you should release only once. There are no two allocations. Assigning one variable to another 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 one undefined behavior.

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

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

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

Zeroing value of object

What I found curious is that after the free() the value of the object allocated to that address was considered 0. It gives the impression that the function free() It was worth it, but it’s not meant to be. Of course the compiler is free to do whatever he wants, but it would cost and C encourages not to put hidden costs that may not be necessary. In general the 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 the release of application memory can free the memory to the operating system. This occurring the address is not released to access by the application. Interestingly does not give error and only accesses a neutral value. I stood on my head because it probably costs something. Doesn’t mean it’s that, there may be a change in the same value, you’d have to search his compiler or library to identify what he does.

It may happen only in mode debug, what 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 the performance is not problem, but it seems a bad solution.

Gazing the source allocation may have occurred a half-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 in this situation the value of the object. This does not mean that it will always occur, but happened a case that did not release to the operating system, but had an internal memory management processing that used the memory within the free().

Then I keep thinking that even the printf() could, in theory, have done something that overwritten the value while he was processing the print. I don’t think it’s good and I think it’s less likely. I don’t remember this function making an allocation on heap.

2

In doing ponteiro2 = ponteiro1, ponteiro2 is not pointing to ponteiro1, but are sharing the same memory address since you are assigning to it the value of ponteiro1 which is this memory address.

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

In doing free (ponteiro2), you are releasing the memory address shared by both pointers. At this time, both ponteiro1 how much ponteiro2 are pointing to an address that is no longer reserved for them.

Now trying to access *ponteiro1 or *ponteiro2, the error of Segmentation fault - "error that occurs when a program tries to access (read or write) 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 nor the ponteiro2, unless you want to do ponteiro1 = NULL and ponteiro2 = NULL if you want to use the variables again later.

  • 1

    More about segmentation fault: https://pt.wikipedia.org/wiki/Falha_de_segmenta%C3%A7%C3%A3o

Browser other questions tagged

You are not signed in. Login or sign up in order to post.