Home > Back-end >  What happens to a pointer after what it's been pointing to has been freed
What happens to a pointer after what it's been pointing to has been freed

Time:05-09

Background info: My program involves creating a hash table and one of my functions is free_hash(struct hash_table *table).

struct hash_table *table points to an array of struct hash_entry pointers. To test my free_hash function in main I have a void *test_free = what. the declaration and initialization for what is hash_table *what = new_hash(array_size).

this is struct hash_table *new_hash() it returns a function that returns a pointer to a new initialized struct hash_table.

My question: After freeing what, eg.free_hash(what), what happens to test_free. What is the address of it/the value of what it is pointing at. And is there any other way I can make sure that what has been destructed/freed.

CodePudding user response:

test_free and what are pointers. The value they have is basically an address. And you assigned the same address to both of them. Nothing happens to either variable once you free that to which they point.

Once you do, the pointers are deemed to be indeterminate, so it becomes undefined behaviour to deference either one. But there's nothing in either variable that indicates this. The onus is on the programmer to ensure no attempts is made to access a freed structure.

As for checking if everything was properly freed, there's -fsanitize=address, valgrind, etc.

CodePudding user response:

C 2018 6.2.4 2 says “… The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.” When you release memory with free, the lifetime of any objects in it end, so any pointers to this memory become indeterminate. “Indeterminate” means the pointer value is not even fixed; it may act as if it has a different value each time it is used.

This rule exists because there have been C implementations in which maintaining pointers required auxiliary information associated with the allocated memory. So the “value” of a pointer was not represented just by the bits directly in the memory used for the pointer object itself. Once the memory, and its auxiliary information, are released, it might no longer be possible to interpret the value of the pointer correctly.

In most modern C implementations, addresses are implemented simply as numbers in a “flat” address space. In this case, no auxiliary information is needed to interpret the value of a pointer or to work with it as by adding offsets to it. However, because the rule exists, optimizers in compilers may treat any pointer to freed memory as indeterminate.

For example, in this code:

void *x;
free(p);
if (SomeTest)
    x = p;
else
    x = q;
printf("%p\n", x);

the compiler is allowed to optimize this to:

void *x;
free(p);
x = q;
printf("%p\n", x);

even if SomeTest is true. That is the fact that p is indeterminate after free means it is allowed to have any value, so it could have the value of q, so the if statement would just be:

if (SomeTest)
    x = q;
else
    x = q;

which of course can be optimized to x = q;.

In short, once you release memory, the C standard does not give you any assurance your program will behave as if a pointer to that memory has any particular value. It may act as if the pointer has a different value each time the program uses it.

  • Related