Setting variable to NULL after free

2019-01-01 14:35发布

In my company there is a coding rule that says, after freeing any memory, reset the variable to NULL. For example ...

void some_func () 
{
    int *nPtr;

    nPtr = malloc (100);

    free (nPtr);
    nPtr = NULL;

    return;
}

I feel that, in cases like the code shown above, setting to NULL does not have any meaning. Or am I missing something?

If there is no meaning in such cases, I am going to take it up with the "quality team" to remove this coding rule. Please advice.

23条回答
查无此人
2楼-- · 2019-01-01 14:56

Setting a pointer to NULL after free is a dubious practice that is often popularized as a "good programming" rule on a patently false premise. It is one of those fake truths that belong to the "sounds right" category but in reality achieve absolutely nothing useful (and sometimes leads to negative consequences).

Allegedly, setting a pointer to NULL after free is supposed to prevent the dreaded "double free" problem when the same pointer value is passed to free more than once. In reality though, in 9 cases out of 10 the real "double free" problem occurs when different pointer objects holding the same pointer value are used as arguments for free. Needless to say, setting a pointer to NULL after free achieves absolutely nothing to prevent the problem in such cases.

Of course, it is possible to run into "double free" problem when using the same pointer object as an argument to free. However, in reality situations like that normally indicate a problem with the general logical structure of the code, not a mere accidental "double free". A proper way to deal with the problem in such cases is to review and rethink the structure of the code in order to avoid the situation when the same pointer is passed to free more than once. In such cases setting the pointer to NULL and considering the problem "fixed" is nothing more than an attempt to sweep the problem under the carpet. It simply won't work in general case, because the problem with the code structure will always find another way to manifest itself.

Finally, if your code is specifically designed to rely on the pointer value being NULL or not NULL, it is perfectly fine to set the pointer value to NULL after free. But as a general "good practice" rule (as in "always set your pointer to NULL after free") it is, once again, a well-known and pretty useless fake, often followed by some for purely religious, voodoo-like reasons.

查看更多
美炸的是我
3楼-- · 2019-01-01 14:56

From the ANSI C standard:

void free(void *ptr);

The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by the calloc , malloc , or realloc function, or if the space has been deallocated by a call to free or realloc , the behavior is undefined.

"the undefined behavior" is almost always a program crash. So as to avoid this it is safe to reset the pointer to NULL. free() itself cannot do this as it is passed only a pointer, not a pointer to a pointer. You can also write a safer version of free() that NULLs the pointer:

void safe_free(void** ptr)
{
  free(*ptr);
  *ptr = NULL;
}
查看更多
只若初见
4楼-- · 2019-01-01 14:56

To the original question: Setting the pointer to NULL directly after freeing the contents is a complete waste of time, provided the code meets all requirements, is fully debugged and will never be modified again. On the other hand, defensively NULLing a pointer that has been freed can be quite useful when someone thoughtlessly adds a new block of code beneath the free(), when the design of the original module isn't correct, and in the case of it-compiles-but-doesn't-do-what-I-want bugs.

In any system, there is an unobtainable goal of making it easiest to the right thing, and the irreducible cost of inaccurate measurements. In C we're offered a set of very sharp, very strong tools, which can create many things in the hands of a skilled worker, and inflict all sorts of metaphoric injuries when handled improperly. Some are hard to understand or use correctly. And people, being naturally risk averse, do irrational things like checking a pointer for NULL value before calling free with it…

The measurement problem is that whenever you attempt to divide good from less good, the more complex the case, the more likely you get an ambiguous measurement. If the goal is do keep only good practices, then some ambiguous ones get tossed out with the actually not good. IF your goal is to eliminate the not good, then the ambiguities may stay with the good. The two goals, keep only good or eliminate clearly bad, would seem to be diametrically opposed, but there is usually a third group that's neither one nor the other, some of both.

Before you make a case with the quality department, try looking through the bug data base to see how often, if ever, invalid pointer values caused problems that had to be written down. If you want to make real difference, identify the most common problem in your production code and propose three ways to prevent it

查看更多
梦寄多情
5楼-- · 2019-01-01 14:57

To add to what other have said, one good method of pointer usage is to always check whether it is a valid pointer or not. Something like:


if(ptr)
   ptr->CallSomeMethod();

Explicitly marking the pointer as NULL after freeing it allows for this kind of usage in C/C++.

查看更多
无与为乐者.
6楼-- · 2019-01-01 14:57

There are two reasons:

Avoid crashes when double-freeing

Written by RageZ in a duplicate question.

The most common bug in c is the double free. Basically you do something like that

free(foobar);
/* lot of code */
free(foobar);

and it end up pretty bad, the OS try to free some already freed memory and generally it segfault. So the good practice is to set to NULL, so you can make test and check if you really need to free this memory

if(foobar != null){
  free(foobar);
}

also to be noted that free(NULL) won't do anything so you don't have to write the if statement. I am not really an OS guru but I am pretty even now most OSes would crash on double free.

That's also a main reason why all languages with garbage collection (Java, dotnet) was so proud of not having this problem and also not having to leave to developer the memory management as a whole.

Avoid using already freed pointers

Written by Martin v. Löwis in a another answer.

Setting unused pointers to NULL is a defensive style, protecting against dangling pointer bugs. If a dangling pointer is accessed after it is freed, you may read or overwrite random memory. If a null pointer is accessed, you get an immediate crash on most systems, telling you right away what the error is.

For local variables, it may be a little bit pointless if it is "obvious" that the pointer isn't accessed anymore after being freed, so this style is more appropriate for member data and global variables. Even for local variables, it may be a good approach if the function continues after the memory is released.

To complete the style, you should also initialize pointers to NULL before they get assigned a true pointer value.

查看更多
梦醉为红颜
7楼-- · 2019-01-01 14:58

If you reach pointer that has been free()d, it might break or not. That memory might be reallocated to another part of your program and then you get memory corruption,

If you set the pointer to NULL, then if you access it, the program always crashes with a segfault. No more ,,sometimes it works'', no more ,,crashes in unpredictible way''. It's way easier to debug.

查看更多
登录 后发表回答