Why is this a common practice to have assert
macro do something useful only in debug configuration? If it exists to test invariants and detect coding bugs, then would not it be easier to go ahead and do the same big boom in production software?
I have some S60 background and there exist __ASSERT_ALWAYS
and __ASSERT_DEBUG
, where the latter is equivalent to assert
.
Asserts are made for stuff that should never happen, i.e. if it does then there is a bug in your code that you need to fix. Releases are builds that are "supposed" to be bug free, and killing application with the assert for the user is as bad as any other faulty behavior.
Checking for assertion costs. You have extra operations that you may not want to exist in the final product. If assertions were always going to work, then people would start using them less "to not kill performance". And believe me, there are a lot of people out there who consider the extra checks a performance kill and would avoid it. These are the same people who actually have to use assert more!
A more important reason is that, assert
, if failed, will just abort your program. There is no usefulness in that whatsoever for the end user (except perhaps for security, to avoid running code with unexpected data, but that's arguably better handled by actual error checking). If you want your program to actually terminate with a message or do something useful, you would have to write your own assert. In that case, you can of course choose to keep it in release mode also.
Finally, assertion helps you find bugs, especially hidden bugs, but in the execution of the software, they may actually not happen. Imagine the following code:
struct X
{
// other stuff
int stage;
};
X x;
... do some stuff
assert(x.stage == STAGE_2);
x.stage = STAGE_3; // go to next stage
... do more stuff
In such an example, your logic says x
should be in STAGE_2
. If it is not, it's a bug. However, if you remove the assert, fix x.stage
and move on, there is hope that the bug is not so severe. In such a case, the end-user can actually continue working without noticing this. If you had kept assert
in release mode too, you would force the application to exit over a bug that didn't have any visible effect.
In reality, you get updates all the times for your software, in which they claim they have fixed bugs. Some of those, are indeed bugs that assert
would have caught. However, you as the end-user didn't have any problem and were actually happy that you weren't interrupted due to those assert
s, weren't you?
I think it's a cultural thing. The arguments in favour removing this kind of check in production code go like this:
The arguments against run as follows
Personally, I ship software that's built exactly as it's tested, asserts and all. But, a lot depends on your customer base and how you hope to schedule releases...
This article is worth a read:- http://www.martinfowler.com/ieeeSoftware/failFast.pdf
but what about when you deploy the software to customers? We don’t want the application to crash just because there’s a typo in a configuration file. One reaction to this fear is to disable assertions in the field.
Don’t do that! Remember, an error that occurs at the customer’s site made it through your testing process. You’ll probably have trouble reproducing it. These errors are the hardest to find, and a well-placed assertion explaining the problem could save you days of effort.
One other thing - in C++, using BOOST_ASSERT you can set it to throw an exception on assertion failure, which makes handling and potentially recovering from assertion failures even more useful. we use this in conjunction with MadExcept so that any assert failures in the field can be easily posted by the user into our bug tracker, with complete call stacks, screenshots, whathaveyou.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With