G
G G
memory allocated on the heap once freed should the pointer be assigned NULL?
G G said:memory allocated on the heap once freed should the pointer be assigned NULL?
memory allocated on the heap once freed should the pointer be assigned NULL?
G G said:memory allocated on the heap once freed should the pointer be assigned NULL?
G G said:memory allocated on the heap once freed should the pointer be assigned NULL?
It can't hurt since any attempt to use the now invalid pointer
again would lead to an immediate crash of the program. But then
it depends a bit on circumstances: if the free() is at the end
of a function and there's no chance that the pointer is acci-
dentally used again, then there's not much good it will do.
And, of course, each free() will have to be followed by
another line of code, which can become tedious and make
things a bit harder to read - unless you use a macro like
#define safe_free( addr ) \
do { \
free( addr ); \
addr = NULL; \
} while ( 1 == 0 )
instead of free() everywhere. I've done that in several cases
where I felt the need to be paranoid;-)
memory allocated on the heap once freed should the pointer be assigned NULL?
It can't hurt since any attempt to use the now invalid pointer
again would lead to an immediate crash of the program. But then
it depends a bit on circumstances: if the free() is at the end
of a function and there's no chance that the pointer is acci-
dentally used again, then there's not much good it will do.
And, of course, each free() will have to be followed by
another line of code, which can become tedious and make
things a bit harder to read - unless you use a macro like
#define safe_free( addr ) \
do { \
free( addr ); \
addr = NULL; \
} while ( 1 == 0 )
instead of free() everywhere. I've done that in several cases
where I felt the need to be paranoid;-)
Unfortunately, this doesn't help with situations like
a = malloc(size);
b = a;
safe_free(a);
so it's always struck me as a giving a false sense of security.
Kaz Kylheku said:it helps in situations like
safe_free (proxy->obj); /* proxy is the only gateway to obj */
In situations where you you deal with the shared reference problem, perhaps
with reference counting, it also helps. Even if proxy is not the only way to
reach obj, it makes sense to do:
drop_ref (proxy->obj); /* drop_ref is a macro which also sets obj to null */
proxy may well have had the last reference to obj. We have no right to access
obj through proxy, even if obj still exists. Since we have no right to access
obj through proxy, it's best to null out the pointer, so that any attempt to do
so is flagged as a null pointer dereference.
In other words, the management of multiple copies is a separate, problem; it
doesn't invalidate the setting of just one copy to null, which can still a
valuable approach when we have somehow addressed the management of sharing.
It can't hurt since any attempt to use the now invalid pointer
again would lead to an immediate crash of the program.
This is simply not true, relying on the assumption will end in pain (or
at least subtle bugs). I come from an x86 OS development background
where the problem is particularly prevalent.
This is simply not true, relying on the assumption will end in pain (or
at least subtle bugs). I come from an x86 OS development background
where the problem is particularly prevalent.
The set of systems where the value 0 is actually an invalid pointer is
increasingly small. All x86 systems as well as most ARM and MIPS
systems can be up so the value 0 is a genuine pointer[1]. Under the
POSIX standard by which UNIX as well as Linux and the BSDs abide,
functions such as mmap()[2] can be used to put valid memory under a
pointer whose value is 0.
From an OS point of view, accidentally dereferencing a NULL pointer is
particularity bad as, while it will tend to result in a crash, malicious
userspace can use the bug to its advantage.
I wish to add that I am not advocating avoiding the use of NULL. I
would certainly encourage people to explicitly invalidate their pointers
if the pointers are not immediately going out of scope[3]. However,
don't fall into the trap of assuming that use of a NULL pointer will
result in a program crash.
"do { ... } while (0)" is the usual idiom for writing a macro that can
be used in a context requiring a statement; the "1 == 0" just seems
(mildly) obfuscated.
I have seen even 'while (__LINE__ == -1)' there to silence a warning
of particular compiler that sometimes complained about condition
being constant expression (like on case of '0' or '1 == 0' but not on
case of '__LINE__ == -1').
#include <stdlib.h>The Sun Studio compiler, for one, has a horrible function call diagnostic
pass that runs before macros are expanded. It's really annoying.
For example, I have code like:
static struct fifo *fifo_init(struct fifo *, void *, size_t);
#define fifo_init3(...) (fifo_init)(__VA_ARGS__)
#define fifo_init1(fifo) fifo_init3((fifo), (void *)0, 0U)
#define fifo_init(...) XPASTE(fifo_init, NARG(__VA_ARGS__))(__VA_ARGS__)
If you use the 1-argument form, the code uses dynamic memory. Otherwise it
uses the fixed-sized buffer provided. When using the 1-argument form, Sun
Studio complains about passing the wrong number of arguments to the
fifo_init routine.
Eh?
cat m.c
william@solaris:/tmp$ cat m.c
#include <stdlib.h>
#define NARG_(_8, _7, _6, _5, _4, _3, _2, _1, N, ...) N
#define NARG(...) NARG_(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1)
#define PASTE(a, b) a ## b
#define XPASTE(a, b) PASTE(a, b)
struct fifo;
struct fifo *fifo_init(struct fifo *, void *, size_t);
#define fifo_init3(...) (fifo_init)(__VA_ARGS__)
#define fifo_init1(fifo) fifo_init3((fifo), (void *)0, 0U)
#define fifo_init(...) XPASTE(fifo_init, NARG(__VA_ARGS__))(__VA_ARGS__)
void f( struct fifo* ff ) {
fifo_init(ff);
}
william@solaris:/tmp$ c99 m.c -c
"m.c", line 18: warning: argument mismatch
On 04/24/2014 03:38 AM, �� Tiib wrote:
...
__LINE__ is replaced by the actual line number in translation phase 4;
from that point on, if the line number happens to be 54, that construct
is indistinguishable from 54 == -1. I wonder how that compiler made its
decision not to warn about that construct, while warning about 1==0?
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.