Ok, so UT_ASSERT is great, but mainly as a building block for more
serious work. I've introduced 4 new macros to help us check pre and post
conditions, and "impossible" situations:

/*!
 * This line of code should not be reached
 */
#define UT_ASSERT_NOT_REACHED() 

/*!
 * Just return from a function if this condition fails
 */
#define UT_return_if_fail(cond)

/*!
 * Just return this value from a function if this condition fails
 */
#define UT_return_val_if_fail(cond, val)

/*!
 * Throw if this condition fails
 */
#define UT_throw_if_fail(cond, val)

All of these macros call UT_ASSERT if they fail, so in DEBUG builds,
you'll still get your UT_ASSERT message at the appropriate file and
line. What got me to do this is, which does nothing in NDEBUG builds:

UT_strdup(const char * str)
{
        UT_ASSERT(str);
        
        ... continue as if nothing has happened if str is null
}

I *don't* want to see any more UT_ASSERTs used, except when used with
UT_TODO, UT_NOT_IMPLEMENTED, UT_SHOULD_NOT_HAPPEN, and even then they
should be used sparingly. UT_ASSERT_NOT_REACHED should be used in
UT_SHOULD_NOT_HAPPEN's place.

Please code defensively. Use these where they make sense. The real bug
is in a level higher than UT_strdup, I admit, but in a lot of conditions
returning an error code, throwing an exception, or just plain returning
from a function is a lot better than segfaulting or moving around in an
unknown unstable state.

We still get the assertion message on the command line. We still should
correct the problem at a higher level, where appropriate. These tools
will help.

Dom

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to