Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why assert macro makes use only for debug build

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.

like image 939
Roman Saveljev Avatar asked Aug 02 '12 13:08

Roman Saveljev


3 Answers

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.

like image 113
yuri kilochek Avatar answered Nov 11 '22 03:11

yuri kilochek


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 asserts, weren't you?

like image 38
Shahbaz Avatar answered Nov 11 '22 02:11

Shahbaz


I think it's a cultural thing. The arguments in favour removing this kind of check in production code go like this:

  • It makes your code run slower.
  • It makes the final executable larger.
  • Your code shouldn't have bugs in once it ships.
  • It will cause your program to exit suddenly and violently, with possible loss of data.

The arguments against run as follows

  • You're shipping the exact code that you tested.
  • Debugging problems reported in the field gets much easier
  • Regardless of what you'd like to think, the code you ship WILL have bugs
  • Performance and size effects are typically minimal.
  • Failing fast may be preferable to attempting to continue when your program is in an undesired state.

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.

like image 26
Roddy Avatar answered Nov 11 '22 03:11

Roddy