Archived

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

tuxx

Assert

Recommended Posts

In my Direct3D application, instead of using the defensive if(FAILED(...))), I decided to use assert(...). This worked great for me in debug mode. However, as someone pointed out to me, ''...'' won''t get called in the release build because assert gets compiled out. Well, they''re obviously right. Is there a version of assert that is made for defensively calling functions, not calling a function on the return type and asserting the return type? If not, is there source code to assert, or an assert-like function? Or should I just bite the bullet and declare a glocal HRESULT and do something like:
assert(hr=g_pd3d->CreateDevice());
 
Or I could also just do something like:
#define Assert(exp) (HRESULT hr; assert(hr=exp))
 
What do yo guys think is the best way of going about this? Thanks!

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
assert looked something like this in CBuilder4 (this is from memory, but I''m possitive it''s something like this):


  
#ifndef NDEBUG
#define assert(a) if(a) exit(0);else void;
#else
#define assert(a) void;
#endif


You could always define assert in a debug build manualy...


  
#undef assert
#define assert(a) if(a) exit(0); else void;

Share this post


Link to post
Share on other sites
hmmm... Thanks, I should try that. But wouldn't your code be something like:

    
#ifdef NDEBUG
#undef assert
#define assert(a) if(!a) exit(0); else void;

?

Well, anyways, I think I should try that. Thanks!

p.s.

Could I do this?

  
#ifndef NDEBUG
#undef assert
#define assert(exp) (exp)
#endif

? That way I could just execute the expression

[edited by - tuxx on July 18, 2002 2:30:52 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by Gee
You''re using assert wrong... It should halt for errors in your code, not errors your graphics card might give you...


Errors are errors. If a function can return an error condition, it''s perfectly acceptable to use assert on it. I suggest you do more reading on what assertions are, and what they can be used for.

One thing, tho; if a function has a non-zero error condition, the assertion should check for equality to the success condition.



Don''t listen to me. I''ve had too much coffee.

Share this post


Link to post
Share on other sites
You''re right! I''m still going to use assert though (even if it''s wrong ), because it provides information on the line that backfired (it beats "Couldn''t ").

Share this post


Link to post
Share on other sites
Wow I'm gettin a lot of replies... That last message was in reply to the first poster. I'll try lookin up verify!

edit: Chris: How do I find the sources?

[edited by - tuxx on July 18, 2002 2:56:51 PM]

Share this post


Link to post
Share on other sites
Well, either we disagree on the point of assert, or I have missunderstood what hr=g_pd3f->CreateDevice() can return.

But I still say if you see an assertion you have a bug in your code, not errors that can vary on different computers and hardware profiles... And if you suggest I should go and "read on what assertion is", then I''ll tell you that''s what I''ve read!

Maybe it''s my sources that''s been flawned, and if I''m wrong, do correct me...

/G

Share this post


Link to post
Share on other sites
I side with Gee. You should not use assert for things that could very well happen when the program is in the hands of end users. The purpose of using assert is to place sanity checks in your own code to find your own logic errors.

This is not to say that you should not have any error-handling code in your release program, but merely that you need to use a different error-handling mechanism. There are far more elegant ways to handle errors than simply halt the program and report some obscure register values to the end user.

Share this post


Link to post
Share on other sites
Expirement with __LINE__ and __FILE__ (if your compiler supports them) to create perhaps a log file system... You wanted to know more specific where the error took place, so there you go...

Although don''t use __LINE__ and __FILE__ within the log function, use it perhaps as a parameter in your log output function... then you can always make a macro that automatically includes them.

/G

Share this post


Link to post
Share on other sites
Thanks. I agree, Gee, with you, so I think I''ll do my own asserts. Two types of asserts, in fact: one your standard assert with the addition of the functionality of verify. The second, pretty much a macro for if(FAILED(...()))

Share this post


Link to post
Share on other sites
7I wrote a TESTHR macro to cook hresults.
It's not a bad idea to assert on a HRESULT failure, but you also want to propegate the failure up the call chain. If it's a show-stopper, you could throw an exception if you wanted to (you can throw your own exception object, and put whatever you want in it, such as the line & file).

If you do make a macro that always executes it's parameter - don't call it assert, assert's de facto behavior is to only execute the parameter in a debug build.


  
void __cdecl HR2String(HRESULT hr, char* szHR);

#ifdef _DEBUG

#define TESTHR(Test_)

if(S_OK!=(hr=Test_) && (S_FALSE!=Test_))
{
char szError[256];
HR2String(hr, szError);
if(FAILED(hr))
{
sprintf(&szError[strlen(szError)], " 0x%x\n%s\nOn line %i in %s\n\n\0", hr, #Test_, __LINE__, __FILE__);
assert(strlen(szError)<sizeof(szError));
OutputDebugString("*****************\n");
OutputDebugString(szError);
return(hr);
}
else
{
sprintf(&szError[strlen(szError)], " 0x%x\n%s\nOn line %i in %s\n\n\0", hr, #Test_, __LINE__, __FILE__);
assert(strlen(szError)<sizeof(szError));
OutputDebugString("*****************\n");
OutputDebugString(szError);
}
}
#else

#define TESTHR(Test_) if(FAILED(hr=Test_)) return(hr);

#endif


//.cpp

#define HR2StringCase(Case_)\

case Case_:
strcpy(szHR, #Case_);
break;

#define HR2StringCase_(HR_, Msg_)

case HR_:
strcpy(szHR, #Msg_);
break;

void __cdecl HR2String(HRESULT hr, char* szHR)
{
switch(hr)
{
HR2StringCase(S_OK)
HR2StringCase(S_FALSE)
//on & on & on ...


default:
{
if(hr>0)
{
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, hr, 0, szHR, 80, 0);
}
else
{
strcpy(szHR, "Unknown Failure: 0x");

itoa(hr, &szHR[strlen(szHR)], 16);
strcpy(&szHR[strlen(szHR)], " (");
itoa(hr, &szHR[strlen(szHR)], 10);
strcpy(&szHR[strlen(szHR)], ")");
}
}
}

Note that the line continuation characters have been removed because the board interprets them...

[edited by - Magmai Kai Holmlor on July 18, 2002 9:25:19 PM]

Share this post


Link to post
Share on other sites