Tim Janik wrote:
> hey All.
> 
> i'd like to propose to turn g_assert and friends like g_assert_not_reached
> into warnings instead of errors. i'll give a bit of background before the
> details though.

Like Mathias, I was in a bit of "hell no!" mode when I first read this. 
  After reading your rationale, I'm less opposed, but... well, still 
opposed.

> the main reasons we use g_return_if_fail massively throughout the glib and
> gtk+ code base is that it catches API misuses verbosely and gives programmers
> a chance to fix their code. this could be achieved with either a g_warning
> (mourn on stderr) or a g_error (mourn and abort).
> 
> the reasons for the default behavior to use g_warning:
> a) a warning usually fullfills its purpose, the programmer knows there's
>     something to fix and can start to trace the root cause.
> b) for easy tracing in gdb with backtraces, programmers can use
>     --g-fatal-warnings to force abort behavior.
> c) programs that aren't 100% bug free could possibly trigger these warnings
>     during production. aborting would take all the end user data with it,
>     created/modified images, text documents, etc.
>     issuing just a warnig preserves the possibility to still save crucial
>     data if the application logic state still permits (which is most often
>     the case in practice).

This is reasonable, and pretty much covers why I use g_return_if_fail() 
and friends.

> in a recent discussion, i figured that (c) perfectly applies to g_assert
> and g_assert_if_reached() also.

Sorry, but I just don't buy it.  When I use g_assert(), my thinking is: 
"this is something that's a pretty bad bug on my part, and if the 
assertion fails, I'm almost 100% sure that the program is going to crash 
very very soon, and possibly in unpredictable ways."

> for a few reasons:
> 1) allow users to save their data if still possible; i.e. (c) from above.

If I think it's possible for users to still do something meaningful with 
the program, I'll use a g_return_if_fail() or a custom if(foo) { 
g_warning(); do_something(); } type thing. That's why we have the 
separate macros in the first place!  g_return*() are for cases where the 
programmer thinks recovery might be possible, and g_assert*() is where 
it isn't possible.

> 3) assertions can help to document programmer intentions and frequent (but
>     regulated) use as we have it with g_return_if_fail can significantly
>     reduce debugging time. i have so far been fairly strict about not adding
>     assertions to the glib/gtk+ core though, because they also tend to make
>     the code and end-user experiences more brittle, especially an
>     occasional wrong assertions that'd have to be revoked upon closer
>     inspection.

And that's the right approach, IMO: use assertions sparingly.  Sometimes 
one might be a mistake, and you fix it.

>     conditionalizing the abort removes the brittleness and allows for
>     adding more helpful assertion statements.

No, it doesn't.  Changing a g_assert*() to a g_return*() when you 
realise aborting is unnecessary is the way to go.

> note that in practice, this shouldn't change anything for programmers
> (except for the ability to write better code ;)
> because of G_DISABLE_ASSERT, programmers can already not rely on
> failing assertions to abort their programs (only g_error will reliably
> do that).

... which I think is pretty broken.  You shouldn't be able to disable 
asserts and pre-condition checks (G_DISABLE_CHECKS) at compile time. 
They were put there for a reason.

> it should however take down programs in end user scenarios less often,
> and code review can be more lax about adding assertions.

No -- instructing programmers to make *proper* use of g_assert*() (and 
to use g_return*() otherwise) will bring programs down less often.  Or 
maybe not -- maybe everyone uses it "properly" and this problem you just 
doesn't exist.

Also...  The documentation tells us what g_return*() and g_assert*() do. 
  If you change this, you're essentially changing the API of glib. 
That's... not cool.  You can argue that G_DISABLE_CHECKS and 
G_DISABLE_ASSERT will do this anyway, but that's a choice on the person 
who builds the code (and again, I'd argue that the existence of those 
defines is a *really* bad idea).  IMO, if you build with 
G_DISABLE_(CHECKS|ASSERTS), you get to keep the pieces when things break.

        -brian

_______________________________________________
gtk-devel-list mailing list
gtk-devel-list@gnome.org
http://mail.gnome.org/mailman/listinfo/gtk-devel-list

Reply via email to