2

This Question statement is came in picture due to statement made by user (Georg Schölly 116K Reputation) in his Question Should one really set pointers to `NULL` after freeing them?

if this Question statement is true

Then How data will corrupt I am not getting ?

Code

#include<iostream>
int main()
{
    int count_1=1, count_2=11, i;
    
    
    int *p=(int*)malloc(4*sizeof(int));
    
    std::cout<<p<<"\n";
    
    for(i=0;i<=3;i++)
    {
        *(p+i)=count_1++;
    }
    
    for(i=0;i<=3;i++)
    {
        std::cout<<*(p+i)<<" ";
    }
    
    std::cout<<"\n";
    free(p);
    
    
    
    p=(int*)malloc(6*sizeof(int));
    
    std::cout<<p<<"\n";
    
    for(i=0;i<=5;i++)
    {
        *(p+i)=count_2++;
    }
    
    for(i=0;i<=3;i++)
    {
        std::cout<<*(p+i)<<" ";
    }
    
}

Output

0xb91a50
1 2 3 4
0xb91a50
11 12 13 14

Again it is allocating same memory location after freeing (0xb91a50), but it is working fine, isn't it ?

Lundin
  • 195,001
  • 40
  • 254
  • 396
Abhishek Mane
  • 619
  • 7
  • 20
  • 1
    The situation is you free a pointer, thereby promising to never use the referenced memory again. Then you do access it. Do we agree on that? – Yunnosch May 21 '21 at 06:38
  • Please provide a [mre] of code which demonstrates the situation you are thinking of (which hopefully is the one I described above). Let's agree that "accessing" means "write-accessing". Then users can point out misunderstanding until the MRE does provoke the relevant situation. Then answers can be made pointing out where corruption can occur. You need to clarify your question by creating (with help if necessary) such a MRE. You need to provide the sitation details and get them to match the situation discussed. Note, with that detail clarified I will consider the question upvotably useful. – Yunnosch May 21 '21 at 06:46
  • @Yunnosch yeah I agree, you are right but if let say we view like this. Memory are two types consumed memory and free memory. we freed memory which `ptr` is pointing to okay , then that memory become part of free memory. So why is there need to differentiate between free memory and freed memory(which is just before consumed memory). – Abhishek Mane May 21 '21 at 06:48
  • No need to differentiate. If you access memory that was never given to you via malloc then you have the same problem. It is just that most programmers know not to do that and it is more obvious if it is done. You can include that situation into your MRE. – Yunnosch May 21 '21 at 06:50
  • @Yunnosch okay but statement quoted by Georg Schölly does not say that, it particularly talk about that memory only given by malloc. So do you say he is wrong – Abhishek Mane May 21 '21 at 06:53
  • Do you see a difference between "what a freed pointer references" and "what you got from malloc and already called free() on"? – Yunnosch May 21 '21 at 06:54
  • @Yunnosch sorry I am not getting you – Abhishek Mane May 21 '21 at 06:57
  • That is why you should make a MRE as a foundation for discussion. – Yunnosch May 21 '21 at 06:58
  • 1
    just give me some time then – Abhishek Mane May 21 '21 at 06:58
  • Absolutely. I recommend to notify the authors of existing answers, to give them a chance to verify that the new question version does not invalidate their answers. – Yunnosch May 21 '21 at 07:00
  • 1
    The question regards the situation where two *different* pointer variables happen to have the same value because the `free`d one wasn't nulled, and then you accidentally write through the "stale" variable. Your code is reusing the same variable for two different allocations, which is not the same thing (but still not a good idea). – molbdnilo May 21 '21 at 08:50
  • @molbdnilo I got you. But why what I am doing is not idea ? – Abhishek Mane May 22 '21 at 05:10
  • 1
    Reusing the same variable for multiple purposes is a very common source of both bugs and unmaintainable code. – molbdnilo May 22 '21 at 05:24
  • @molbdnilo Noted and Thanks – Abhishek Mane May 22 '21 at 05:34

2 Answers2

3

You do not reuse the old pointer in your code. After p=(int*)malloc(6*sizeof(int));, p point to a nice new allocated array and you can use it without any problem. The data corruption problem quoted by Georg would occur in code similar to that:

int *p=(int*)malloc(4*sizeof(int));
...
free(p);

// use a different pointer but will get same address because of previous free
int *pp=(int*)malloc(6*sizeof(int));

std::cout<<p<<"\n";

for(i=0;i<=5;i++)
{
    *(pp+i)=count_2++;
}

p[2] = 23;             //erroneouly using the old pointer will corrupt the new array
for(i=0;i<=3;i++)
{
    std::cout<<*(pp+i)<<" ";
}
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
2

Setting the pointer to NULL after you free a block of memory is a precaution with the following advantages:

  • it is a simple way to indicate that the block has been freed, or has not been allocated.
  • the pointer can be tested, thus preventing access attempts or erroneous calls to free the same block again. Note that free(p) with p a null pointer is OK, as well as delete p;.
  • it may help detect bugs: if the program tries to access the freed object, a crash is certain on most targets if the pointer has been set to NULL whereas if the pointer has not been cleared, modifying the freed object may succeed and result in corrupting the heap or another object that would happen to have been allocated at the same address.

Yet this is not a perfect solution:

  • the pointer may have been copied and these copies still point to the freed object.

In your example, you reuse the pointer immediately so setting it to NULL after the first call to free is not very useful. As a matter of fact, if you wrote p = NULL; the compiler would probably optimize this assignment out and not generate code for it.

Note also that using malloc() and free() in C++ code is frowned upon. You should use new and delete or vector templates.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • why it is not corrupting data as quoted by `Georg Schölly` as it is getting same memory location – Abhishek Mane May 21 '21 at 07:34
  • 1
    I modified the answer: if the program tries to access the freed object, a crash is certain on most targets if the pointer has been set to NULL whereas if the pointer has not been cleared, modifying the freed object may succeed and result in corrupting the heap or another object that would happen to have been allocated at the same address. – chqrlie May 21 '21 at 07:43
  • `if you wrote p = NULL; the compiler would probably optimize this assignment out and not generate code for it.` can you elaborate this more please. – Abhishek Mane May 22 '21 at 07:55
  • 1
    @AbhishekMane: given the code: `free(p); p = NULL; p = (int*)malloc(6 * sizeof(int));` the compiler would detect that `p = NULL` has no effect before `p = (int*)malloc(6 * sizeof(int));` because 1. `p` is not a volatile object, 2. `p` is a local variable that cannot be accessed by `malloc()`, hence assigning `NULL` to it before reassigning the return value of `malloc()` can be omitted. You can look at the code on https://godbolt.org/z/daehbxWE1 the assignment `movq $0, -24(%rbp)` disappears when switching from `-O0` to `-O2`. – chqrlie May 22 '21 at 09:32