Subject:
|
Re: Design by Contract (long post)
|
Newsgroups:
|
lugnet.robotics.rcx
|
Date:
|
Fri, 9 Jan 2004 10:11:10 GMT
|
Viewed:
|
3414 times
|
| |
| |
In lugnet.robotics.rcx, Iain McInnes wrote:
|
In lugnet.robotics.rcx, Tim McSweeney wrote:
|
<delurk>
The first definition of assert is the correct, standard definition. However
there is a slight boo boo in the original post in the line:
assert (myptr = malloc (sizeof (mystruct));
Which will delete the malloc when NDEBUG is defined. Its a classic mistake
that bites even experienced programmers now and then.
the easy way round it is to write:
myptr = malloc (sizeof (mystruct));
assert(myptr!=NULL);
thus, the malloc always takes place, but the assert only occurs in debug
builds.
|
DoH! Thanks, Tim. I was very careful composing the original post, but
added the example in as an after thought - Well spotted.
Iain.
|
For more fun with asserts:
See if your compiler supports the __FILE__ and __LINE__ macros (or
something equivilant).
#ifdef NDEBUG
#define assert(x) ((void)0)
#else
#define assert(x) if (x) {} else { assert_fail(__FILE__,__LINE__); }
#endif
your assert_fail function can then display the file and line number where the
assert is defined (not necassarily practical on the RCX :) ).
you can also use the # notation in macros to turn paramters into strings, thus:
#ifdef NDEBUG
#define assert(x) ((void)0)
#else
#define assert(x) if (x) {} else { assert_fail(__FILE__,__LINE__,#x); }
#endif
Will pass the condition that failed (as a string) to the assert_fail function.
enabling you to do something like:
printf("assert failed (%s), %s:%s",pCondition,pFile,pLineNum);
The next step is to allow the user/programmer to disable individual asserts un
the fly at run time as they occur.
#ifdef NDEBUG
#define assert(x) ((void)0)
#else
#define assert(x) \
static bool bIsDisabled = false; \
if (x) \
{} \
else \
{ \
if(!bIsDisabled) \
{ \
assert_fail(__FILE__,__LINE__,#x,&bIsDisabled); \
} \
}
#endif
your assert_fail macro now goes into a loop waiting for a button press. (if
you are on a platform with a gui you could pop up a dialog box with buttons)
One button (break) halts execution of the program (or executes a debug break if
the platform supports it). The second button (cancel) sets *pbIsDisabled to
true and returns, this continues execution of the program and prevents this
particular assert from firing again. The third button (continue) leaves
pbIsDisabled alone and returns, program execution continues but this particular
assert will still fire.
Im not seriously proposing that anyone implement these ideas on the RCX, just
thought you might be interested in how powerful asserts can become. At work we
have a standard set of headers that implement these (and a few other) features
and they are very, VERY useful.
Cheers
Tim
|
|
Message has 1 Reply: | | Re: Design by Contract (long post)
|
| Thanks, Tim. I haven't used the #x idiom myself - I like it. Your implementation with the boolean: (...) Will need an extra level of parenthesis surrounding the bool so that its declaration scope is made local. You can certainly go to town with this (...) (21 years ago, 10-Jan-04, to lugnet.robotics.rcx, FTX)
|
Message is in Reply To:
7 Messages in This Thread:
- Entire Thread on One Page:
- Nested:
All | Brief | Compact | Dots
Linear:
All | Brief | Compact
This Message and its Replies on One Page:
- Nested:
All | Brief | Compact | Dots
Linear:
All | Brief | Compact
|
|
|
|