Assert and the optional Message

Jonathan M Davis jmdavisProg at gmx.com
Fri Mar 9 08:56:10 PST 2012


On Friday, March 09, 2012 16:07:10 Timon Gehr wrote:
> On 03/09/2012 03:24 PM, Jacob Carlborg wrote:
> > On 2012-03-09 15:13, Timon Gehr wrote:
> >> On 03/09/2012 01:20 PM, Jacob Carlborg wrote:
> >>> On 2012-03-09 12:12, Jonathan M Davis wrote:
> >>>> On Friday, March 09, 2012 11:03:38 Regan Heath wrote:
> >>>>> On Fri, 09 Mar 2012 08:20:33 -0000, Chris Pons<cmpons at gmail.com>
> >>>>> 
> >>>>> wrote:
> >>>>>> Any idea why, system("PAUSE") does work?
> >>>>> 
> >>>>> As Jonathan says, assert throws AssertError... which means, if you
> >>>>> wanted
> >>>>> to you could catch it, for example...
> >>>>> 
> >>>>> module asserting;
> >>>>> 
> >>>>> import std.stdio;
> >>>>> import core.exception;
> >>>>> 
> >>>>> debug
> >>>>> {
> >>>>> import std.c.windows.windows;
> >>>>> extern (C) int kbhit();
> >>>>> }
> >>>>> 
> >>>>> void main()
> >>>>> {
> >>>>> try
> >>>>> {
> >>>>> assert(false, "testing assert");
> >>>>> }
> >>>>> catch(AssertError e)
> >>>>> {
> >>>>> debug
> >>>>> {
> >>>>> writefln("Assertion failed: %s", e);
> >>>>> writefln("Press any key to exit...");
> >>>>> while(!kbhit())
> >>>>> Sleep(1);
> >>>>> }
> >>>>> throw e;
> >>>>> }
> >>>>> }
> >>>>> 
> >>>>> So, for debug builds your exe will output the assertion manually, and
> >>>>> wait
> >>>>> for a key press. Then re-throw the assertion (resulting in the d
> >>>>> runtime
> >>>>> outputting the assertion again). In release, no pause.
> >>>>> 
> >>>>> Note: kbhit and Sleep are windows specific (sleep would be the unix
> >>>>> equivalent, not sure on one for kbhit).
> >>>> 
> >>>> Bet advised that catching anything not derived from Exception is
> >>>> generally a
> >>>> _bad_ idea (most of which are derived from Error), and AssertError is
> >>>> _not_
> >>>> derived from Exception but rather Error. AssertErrors are not
> >>>> guaranteed to
> >>>> invoke finally blocks, scope statements, or destructors. Your program
> >>>> is in an
> >>>> invalid state when you catch an Error. So, while it may work in this
> >>>> particular case, it is _not_ something that you should be doing in
> >>>> general. By
> >>>> far the worst thing to do would be to catch an Error and then continue
> >>>> executing. Errors are _supposed_ to kill your program.
> >>>> 
> >>>> - Jonathan M Davis
> >>> 
> >>> Then I would say it's bad design to have "assert" throw an AssertError.
> >>> Whatever "assert" throws needs to be catchable, this is essential for
> >>> writing unit test frameworks. It needs to be possible to write a unit
> >>> test framework that catches all AssertErrors and prints a nice report at
> >>> the end (or similar).
> >> 
> >> This is a special case. Jonathan was specifically referring to the
> >> general case.
> > 
> > Then way is it an error?
> 
> So that it does not get caught by catch(Exception){}.
> 
> > I still want it to call finally blocks, scope
> > statements, and destructors.
> 
> I have never actually observed that those are not run for assertion
> failures.

The current implementation may not skip them, but if so, that might actually 
be a bug. Errors are not intended to be recoverable, so you can't rely on them 
hitting finally blocks, scope statements, or destructors. They may very well do 
so at present. While it's not guaranteed that they will, I'm not sure that 
it's guaranteed that they _won't_. So, it may or may not be a bug if they do.

It was never intended that AssertError or any other Error be particularly 
catchable, but it's also true that D is a systems programming language, so 
it'll let you do stuff which is unsafe, so if you know what you're doing, then 
there are circumstances where you can get away with (unit testing is one 
example of where catching AssertErrors might make sense). But you have to know 
what you're doing, since it's _not_ safe.

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list