Re: g_error_free() warning on null pointer



On Sun, Aug 16, 2015 at 10:49:56AM +0100, Emmanuele Bassi wrote:
Consistency is important for a library. It's much simpler to remember
"all free/unref functions accept NULL" instead of "free/g_free accept
NULL, g_object_unref not, g_clear_object yes, etc etc".

unref() is not a free function, so there goes the "consistency"
argument for it.

A free function can be seen as a special case of unref where the pointed
memory can have at most one reference. free and unref are used for the
same purpose, to release memory. Consistency between the two makes
sense. If you need to remember different rules for two similar cases,
then you have an inconsistency.

All the reference counting functions must *not*
accept NULL; if you're unreffing a NULL value then there is reference
counting bug in your code, because it means something is holding a
pointer to an object, nullifying it, and still trying to access it; if
that happens, your code should keep an actual reference. Silently
discarding NULL is going to mask this bug.

If you have a NULL pointer and you unref it, it can mean:
- that the object was never initialized
- that unref has already been called

For the first case, I've given a typical use case: at the end of a
function you release the variables that you don't need anymore; some of
them are maybe not initialized, e.g. if you have an early error and goto
directly to the end of the function.

For the second case, if some code is still trying to access the object,
you'll get warnings when using other public functions, that is, other
functions that do some actual work on the object. The job of unref() is
just to release the reference, if the pointer is NULL it means that the
job is already done. Lots of public functions do a NOP when the job is
already done. Being able to do several times the same operation, to be
sure that it's done, can simplify the code. You don't need to add some
logic to know if the operation is already done or not, you just call the
function.

As a side note: the g_clear_* family of functions is meant to be used
to nullify a pointer variable after freeing its contents; these
functions are NULL-safe because they have to, since they need to
nullify the variable at the given address.

Calling g_object_unref() also generally implies to nullify the pointer,
except if the variable goes out of scope.

What we see nowadays is to call g_clear_*() at the end of a function,
just for convenience to avoid the if(foo != NULL). Even if nullifying
the pointer is useless. It's sort of a small hack. It would work equally
fine if we can do in dispose():

g_object_unref (foo);
foo = NULL;

In C the latter is more natural imo. Setting a variable to NULL after
freeing it is a common pattern.

(it's just one more line, but it would already be more convenient than
having conditions)

--
Sébastien


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]