Archived

This topic is now archived and is closed to further replies.

Advanced ASSERT macro

This topic is 5306 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I put a lot of ASSERT and VERIFY in my code to track errors. However when I compile in release mode, I still want to be able to see when an Assertion error occured. Please tell me if my macro is ok or if there is a better/faster way. I know there are always subtle errors possible with macros!!!

#define NEW_ASSERT(thing)  if(!(thing)) { if (AfxMessageBox("NEW_ASSERT Error!! Ignore?",MB_YESNO|MB_ICONSTOP|MB_APPLMODAL)==IDNO) exit(0); VERIFY(false); } else

Thanks

Share this post


Link to post
Share on other sites
Check out enforce() at www.cuj.com. I use those, they are great.

I''m working on a version for myself, I''mm going to add asm { int 3 } (drop to debugger) in there as well and see if I can get the debugger to step one level up (from the RuntimeException constructor) so you''re pointing RIGHT at the failing statement when it occurs and you''re debugging.

Share this post


Link to post
Share on other sites
Enforce: Link
Good god, that''s overdoing it, isn''t it?

Several ways to improve that assert.
1) output expression that failed: #define assert(expr) { if(!expr) printf(#expr); }
2) together with __FILE__ and __LINE__
3) and call stack, complete with value and type or local variables and parameters (dbghelp 5.1 SymGetTypeInfo)
4) more choices: ignore, ignore always (implement with a static flag)

how ''bout a [ source ] box next time?

Share this post


Link to post
Share on other sites
What''s with the ''else'' on the end there?
Surely if you ignore the assert then you''d want the following code to continue as normal, that ''else'' will skip the following statement if the assertion fails and the user selects ''Ignore''.
Also, make it easier to read by using ''\'':

#define NEW_ASSERT(thing) \
if(!(thing))\
{ \
if (AfxMessageBox("NEW_ASSERT Error!! Ignore?", \
MB_YESNO|MB_ICONSTOP|MB_APPLMODAL)==IDNO) \
exit(0); \
VERIFY(false); \
} \
else


Adding the expression, file name and line number will help as well. Also, having the output logged to a file/console, regardless of the user selection, would be useful.

Skizz

Share this post


Link to post
Share on other sites
quote:
Original post by Jan Wassenberg
1) output expression that failed: #define assert(expr) { if(!expr) printf(#expr); }
2) together with __FILE__ and __LINE__
3) and call stack, complete with value and type or local variables and parameters (dbghelp 5.1 SymGetTypeInfo)
4) more choices: ignore, ignore always (implement with a static flag)


My enforce is much smaller, it throws an exception with the expression, file, line already.

I don''t see the point of a call stack though. The Win32 API function StackWalk64 looks sweet; does anyone have any example code of it?

Share this post


Link to post
Share on other sites
Thanks a lot for the input!

quote:
Original post by Skizz
What's with the 'else' on the end there?
...



If you don't have the 'else' at the end, the following won't compile:



if (functionA())
NEW_ASSERT(functionB());
else
functionC();



You would have an error: 'error C2181: illegal else without matching if'

[edited by - Floating on June 5, 2003 8:34:58 PM]

Share this post


Link to post
Share on other sites
> My enforce is much smaller, it throws an exception with the expression, file, line already.
I believe you. My code is 500 lines, but also does a bit more.

> I don''t see the point of a call stack though. The Win32 API function StackWalk64 looks sweet; does anyone have any example code of it? <
Win32 : StackWalk64? don''t see point of call stack : StackWalk64 looks sweet? hehe
The point is providing debug information in release mode, without a debugger present.
Example code: google pietrek stackwalk

>> If you don''t have the ''else'' at the end, the following won''t compile:
> That''s why you do an inline function. So you don''t have to do the if/else hack
How about enclosing it with { }?

Share this post


Link to post
Share on other sites
Enclosing it with {}?

I would have a similar problem:


if (functionA())
NEW_ASSERT(functionB());
else
functionC();

would become:

if (functionA())
{
if (functionB())
{...}
};
else
functionC();


Share this post


Link to post
Share on other sites
Hmmm...

#define NEW_ASSERT(thing) \
if(thing) \
; \
else \
if (AfxMessageBox("NEW_ASSERT error: " #thing "... ignore?",MB_YESNO|MB_ICONSTOP|MB_APPLMODAL)==IDNO) \
exit(0); \
else \
VERIFY(false);

Share this post


Link to post
Share on other sites
Most correct way to fix the if 'problem' (and most likely the way its done in the official ASSERT macro):
void AssertFunc(char *file, int line, char *expr, bool a);
#define ASSERT(X) AssertFunc(__FILE__,__LINE__, #X, X)


void AssertFunc(char *file, int line, char *expr, bool a)
{
if(!a)
{
// .
// .
// .
}
}


[edited by - Extrarius on June 5, 2003 12:52:13 AM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
if (functionA())
NEW_ASSERT(functionB());
else
functionC();


I hope you realize that this use of ASSERT is about as wrong as it gets ? You call functionB() in debug mode, but omit the call in release. What you probably want to do is check the return value in debug mode and don''t check it in release...

Share this post


Link to post
Share on other sites