To LUGNET HomepageTo LUGNET News HomepageTo LUGNET Guide Homepage
 Help on Searching
 
Post new message to lugnet.robotics.rcxOpen lugnet.robotics.rcx in your NNTP NewsreaderTo LUGNET News Traffic PageSign In (Members)
 Robotics / RCX / 2319
2318  |  2320
Subject: 
Re: Design by Contract (long post)
Newsgroups: 
lugnet.robotics.rcx
Date: 
Thu, 8 Jan 2004 10:58:55 GMT
Viewed: 
3004 times
  
In lugnet.robotics.rcx, Ross Crawford wrote:
   In lugnet.robotics.rcx, Iain McInnes wrote:
   Hi, people.

Hi Iain!

   I have created an assert() macro which works under BrickOS. For those unfamiliar with assert(), it is a standard C macro whose purpose is to help find bugs. It is integral to the ‘design by contract’ style of programming pioneered by Bertrand Meyer.

Cool!

  
#ifdef NDEBUG
#define assert(x) ((void)0)
#else
#define assert(x) if (x) {} else { assert_fail(); }
#endif

I have a question about this: If NDEBUG is defined, shouldn’t it still execute x? That is, shouldn’t the code in assert.h (or wherever) be:
#ifdef NDEBUG
#define assert(x) (x)
#else
#define assert(x) if (x) {} else { assert_fail(); }
#endif
ROSCO

<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. It’s 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.

The reason for deleting the contents of the assert is that asserts commonly consist of a logical check (often slow) that you DON’T want to execute in release builds, e.g.
assert(numAllocs+numFree==countBlocks());
leaving a dangling
numAllocs+numFree==countBlocks();
in release builds would be pointless (especially if countBlocks is a slow function).



Another common solution is define a verify macro, this works almost the same as the assert, but as you suggested still executes the contents of the macro:

#ifdef NDEBUG
#define verify(x) (x)
#else
#define verify(x) if (x) {} else { assert_fail(); }
#endif
then you can write:
verify (myptr = malloc (sizeof (mystruct));
this will execute the malloc in all builds, but only assert in debug builds.


Cheers Tim

</delurk>



Message has 1 Reply:
  Re: Design by Contract (long post)
 
(...) D'oH! Thanks, Tim. I was very careful composing the original post, but added the example in as an after thought - Well spotted. Iain. (20 years ago, 8-Jan-04, to lugnet.robotics.rcx, FTX)

Message is in Reply To:
  Re: Design by Contract (long post)
 
(...) Hi Iain! (...) Cool! (...) I have a question about this: If NDEBUG is defined, shouldn't it still execute x? That is, shouldn't the code in assert.h (or wherever) be: #ifdef NDEBUG #define assert(x) (x) #else #define assert(x) if (x) else (...) (20 years ago, 8-Jan-04, to lugnet.robotics.rcx, FTX)

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
    

Custom Search

©2005 LUGNET. All rights reserved. - hosted by steinbruch.info GbR