-3

According to theory of c programming variable a should be a dangling pointer and it should throw segmentation fault error. But here variable a is still pointing to same memory location.

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

int main() {

    int* a = (int*)malloc(sizeof(int));
    printf("%lu\n", sizeof(a));
    free(a);
    *a = 20;
    printf("%d\n", (*a));
    return 0;
}

output :

8
20

How this can happen ? I executed this program on GCC and Clang both. They both produced the same output.

Dr Phil
  • 833
  • 6
  • 18
  • "it should throw segmentation fault error". Wrong. Accessing invalid memory is undefined behaviour. Which means it may seg fault but it also may have any other behaviour. – kaylum Mar 27 '20 at 12:58

4 Answers4

1

After you have free()-d the allocation, attempt to use that memory invokes undefined behaviour. Segmentation fault is one of the many side effcets of UB, but not the guranteed one.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
0

As others have pointed out already, accessing a freed pointer is undefined behavior.

The reason why it seems "usable" even after the free() call is because in most implementations of free(), this function does not release the memory location immediately to the OS for performance reasons. The freed memory location is now, however, reusable.

Here's an example of possible behavior of malloc() and free():

int* a = malloc(sizeof(int)); // pointer `a` has address 0xABCD
free(a); // address 0xABCD is now considered freed
*a = 5; // this works because nobody has "touched" yet address 0xABCD
int* b = malloc(sizeof(int)); // malloc() will reuse address 0xABCD since it is considered "free"

Of course, this is just a possible behavior.

TL;DR: do not use a pointer after free(), you can't know what will happen. It's an extremely dangerous (and useless) practice.

Luca Polito
  • 2,387
  • 14
  • 20
0

According to theory of c programming variable a should be a dangling pointer and it should throw segmentation fault error.

There is no such theory or rule in C.

Memory allocation reserves memory for your use. Calling free removes the reservation. The free routine is not required to mark the memory as inaccessible.

The C standard defines an abstract model in which malloc reserves space for an object, and free ends the lifetime of that object. Within this model, two rules in the C standard apply in particular to your question. C 2018 6.2.4 2 says:

… If an object is referred to outside of its lifetime, the behavior is undefined…

As used in the C standard, “undefined” means the standard does not impose any requirements. That means the standard does not say you can access the memory, it does not say you cannot access the memory, it does not say your program will behave as if the object is still there, it does not say your program will behave as if they object is not there. It does not say whether your program will crash or not crash. The C standard simply says nothing about what will happen.

That paragraph also says:

… The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.

That means that, after free(a), the value of a is indeterminate. It is no longer specified by the C standard. This rule in the C standard arose because some C implementations had to use various assistive means to refer to memory, such as a pointer containing data that referred to a table or structure with further information. Once the memory is freed, that table or structure may itself be altered or destroyed, and then attempting to use the pointer would fail in various ways. So, in the C model, the value of the pointer is indeterminate. This means your sentence “But here variable a is still pointing to same memory location” is not specified to be true by the C standard. And, while common modern C implementations do not have these pointers relying on additional data, the rule remains a rule, and compilers may take advantage of it in their optimization. So you cannot rely on the value of a pointer after it has been passed to free.

To be clear: You not only cannot rely on the memory that was pointed to by the pointer, you cannot rely on the value of the pointer. Simply executing free(a); if (a == NULL) … has undefined behavior.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
-1

Its undefined behaviour. You may/may not get a seg fault. After free(a), a is a dangling pointer which points to no where. free() just releases the memory block allocated by malloc() and it doesn't change the value of pointer pointing to heap in that process address space. On some platforms you might get segfault if you try dereferencing pointer after freeing. Its good practice if you assign pointer a to NULL after freeing.

Sunil Bojanapally
  • 12,528
  • 4
  • 33
  • 46
  • 1
    And on some other platforms you might just end up with [arbitrary code execution](https://sensepost.com/blog/2017/linux-heap-exploitation-intro-series-used-and-abused-use-after-free/). – Aplet123 Mar 27 '20 at 13:03