Approve and NDEBUG

After reading some threads about abuse of exceptions (basically saying that you don't want to spin the stack if the wrong functions are biased - perhaps by signaling that your whole memory is corrupted or something just as dangerous) I think about using assert () more often. I used to only use assert () as a debugging tool, and I think there are so many C ++ programmers. I am worried that part of my error handling is disabled using the NDEBUG #define introduced in the runtime assembly at some point in the future. Is there a way around this and others have problems with this (e.g. I have to worry about this)?

Thanks Pat

Edit: The point of the streams I read was that if your application is really distorted, then unwinding the stack can damage the system, for example, if the destructor wrote something to a file and the file descriptor was damaged. I do not suggest using assert for normal error handling. The current use case that I have is pretty weak, but look what you think:

//check later code won't crash the system if( buf.length() % 2 ) return false; // do other stuff that shouldn't affect bufs length //copy 2 bytes into buf at a time, if length is odd then don't know //what will happen so use assert to make sure it can't damage anything assert( !(buf.length() % 2) ); for( i = 0; i != buf.length(); i += 2 ) memcpy( buf + i, data, 2 ); 

edit2: discussion here: http://groups.google.com/group/comp.lang.c++.moderated/browse_frm/thread/80083ac31a1188da

+4
source share
6 answers

You can create your own assert instead of using the stock C assert.h. Your approval will not be disabled.

See how assert () is implemented in /usr/include/assert.h (or anywhere). It's just some kind of preprocessing magic that ultimately calls the assert fail function.

In our embedded environments, we replace assert () all the time.

+8
source

I like to define my own approval macros. I always do tests with two ASSERTs (even for optimized builds), and DASSERT only for debug builds. You probably want to use ASSERT by default, but if something is expensive to test, or statements inside the internal loops of performance-sensitive areas can be changed to DASSERT.

Also, remember that statements should only be used for completely meaningless conditions that indicate a logical error in your program and from which you cannot recover. This is a test of the correctness of your programming. Statements should NEVER be used instead of handling errors, exceptions or reliability, and you should never assert anything related to incorrect or incorrect user input - such things should be handled gracefully. An assertion is simply a controlled failure when you have the ability to display additional debugging information.

Here are my macros:

 /// ASSERT(condition) checks if the condition is met, and if not, calls /// ABORT with an error message indicating the module and line where /// the error occurred. #ifndef ASSERT #define ASSERT(x) \ if (!(x)) { \ char buf[2048]; \ snprintf (buf, 2048, "Assertion failed in \"%s\", line %d\n" \ "\tProbable bug in software.\n", \ __FILE__, __LINE__); \ ABORT (buf); \ } \ else // This 'else' exists to catch the user following semicolon #endif /// DASSERT(condition) is just like ASSERT, except that it only is /// functional in DEBUG mode, but does nothing when in a non-DEBUG /// (optimized, shipping) build. #ifdef DEBUG # define DASSERT(x) ASSERT(x) #else # define DASSERT(x) /* DASSERT does nothing when not debugging */ #endif 
+7
source

Well, an unsuccessful statement is a mistake , nothing more, nothing less. Same as dereferencing a null pointer, except that you yourself gave your software a stick to hit you. A bold decision, you deserve it!

Jumping out of the problem with an exception is unlikely to help, it does not fix the error. Therefore, I would recommend implementing your own ASSERT () macro, which:

  • Attempts to collect as much data as possible about the failure (statement of expression, stack trace, user environment, etc.).
  • It’s hard to make it so easy that the user can report it to you, and
  • It opens a window with an apology for the inconvenience and brutally cancels this application.

If performance is a problem, you might consider having some kind of SOFT_ASSERT () macro that disappears from releases.

+4
source

I would not rely on assert for anything other than a random way of checking assumptions during debugging. In the release code, your overridden assert will be handled randomly, this is not user-friendly.

If during debugging your assumption, for example, this condition will never be true, will be invalid. Modify the error handling code to accept this condition.

Otherwise, you have a more convenient means of processing assumptions that violate the conditions. Create an exception called CAssumptionViolated, throw it where you would otherwise claim. Catch it in your main procedure and give the user the opportunity to notify you of an error. It is even better to provide debugging information with an exception. Even better, automatically send debugging information to your organization.

+1
source

Perhaps I did not understand you correctly, but IMO assert () should not be used in release code to do what you describe, for example, to force invariants to be applied.

If the premises of the function are incorrect, what would you like to do? How do you want to report this:

  • interactive user?
  • your support staff

In both cases, you will need to call the error handling code, and (it seems to me) exceptions - this is just a ticket.

However, if you still want to go this route, you can put the following at the beginning of each source file:

 #undef NDEBUG 

I do NOT recommend this. Please do not do this. No one will thank you :-)

Seb

+1
source

I saw how programs implement their own statements and macro checks. Where statements are used in debug mode and checked both in debug mode and in release mode. In particular, the check can be used to gracefully exit (or, rather, more graceful than a direct failure) from the program when the check fails. Probably one of the first and best uses I've seen is in Unreal code (I believe you can still get Unreal headers to take a look).

0
source

All Articles