Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

There's a discussion going on over at comp.lang.c++.moderated about whether or not assertions, which in C++ only exist in debug builds by default, should be kept in production code or not.

Obviously, each project is unique, so my question here is not so much whether assertions should be kept, but in which cases this is recommendable/not a good idea.

By assertion, I mean:

  • A run-time check that tests a condition which, when false, reveals a bug in the software.
  • A mechanism by which the program is halted (maybe after really minimal clean-up work).

I'm not necessarily talking about C or C++.

My own opinion is that if you're the programmer, but don't own the data (which is the case with most commercial desktop applications), you should keep them on, because a failing asssertion shows a bug, and you should not go on with a bug, with the risk of corrupting the user's data. This forces you to test strongly before you ship, and makes bugs more visible, thus easier to spot and fix.

What's your opinion/experience?

Cheers,

Carl

See related question here


Responses and Updates

Hey Graham,

An assertion is error, pure and simple and therefore should be handled like one. Since an error should be handled in release mode then you don't really need assertions.

That's why I prefer the word "bug" when talking about assertions. It makes things much clearer. To me, the word "error" is too vague. A missing file is an error, not a bug, and the program should deal with it. Trying to dereference a null pointer is a bug, and the program should acknowledge that something smells like bad cheese.

Hence, you should test the pointer with an assertion, but the presence of the file with normal error-handling code.


Slight off-topic, but an important point in the discussion.

As a heads-up, if your assertions break into the debugger when they fail, why not. But there are plenty of reasons a file could not exist that are completely outside of the control of your code: read/write rights, disk full, USB device unplugged, etc. Since you don't have control over it, I feel assertions are not the right way to deal with that.

Carl


Thomas,

Yes, I have Code Complete, and must say I strongly disagree with that particular advice.

Say your custom memory allocator screws up, and zeroes a chunk of memory that is still used by some other object. I happens to zero a pointer that this object dereferences regularly, and one of the invariants is that this pointer is never null, and you have a couple of assertions to make sure it stays that way. What do you do if the pointer suddenly is null. You just if() around it, hoping that it works?

Remember, we're talking about product code here, so there's no breaking into the debugger and inspecting the local state. This is a real bug on the user's machine.

Carl

share|improve this question
2  
Why are your responses not comments to the answers? –  Svish Oct 25 '11 at 12:49
7  
Because in 2008 there wasn't a comment system. –  graham.reeds Dec 9 '12 at 22:47
add comment

17 Answers

Allow me to quote Steve McConnell's Code Complete. The section on Assertions is 8.2.

Normally, you don't want users to see assertion messages in production code; assertions are primarily for use during development and maintenance. Assertions are normally compiled into the code at development time and compiled out of the code for production.

However, later in the same section, this advice is given:

For highly robust code, assert and then handle the error anyway.

I think that as long as performance is not an issue, leave the assertion in, but rather than display a message, have it write to a log file. I think that advice is also in Code Complete, but I'm not finding it right now.

share|improve this answer
add comment

Assertions are comments that do not become outdated. They document which theoretical states are intended, and which states should not occur. If code is changed so states allowed change, the developer is soon informed and needs to update the assertion.

share|improve this answer
1  
That is the purpose of a unit test... –  jkschneider May 24 '13 at 18:27
3  
@jkschneider: unit tests function poorly as comments. –  MSalters May 26 '13 at 17:51
2  
@jkschneider: unit tests are for testing things within the scope of the program's code. assertions are for ensuring that assumptions which the code is based on are actually true in reality, before the code continues processing under those assumptions. They're "documentation" in the sense that, if they turn out not to be the case, the program will abort, state the assumption, and indicate that the assumption didn't hold up. You can also read the assertion as documention of that in the code, of course. –  Lee Dec 25 '13 at 1:11
    
This is the best answer because it relates asserts to comments, which is a helpful way of thinking about them. They are a step up from comments because they are constantly machine tested during development, but they should always be meaningful to human readers first. Just like comments, they should not be part of logic or final execution. Just like comments, you can leave them in or take them out depending on whether the language is compiled or interpreted, your roll-out plans, obfuscation strategy, etc. I have seen one case where a comment actually caused a bug, but that was a weird one. –  DaveWalley Feb 25 at 22:57
add comment

Leave assertions turned on in production code, unless you have measured that the program runs significantly faster with them turned off.

"if it's not worth measuring to prove it's more efficient, then it's not worth sacrificing clarity for a performance gamble." -- SteveMcConnell 1993

http://c2.com/cgi/wiki?ShipWithAssertionsOn

share|improve this answer
add comment

In my C++ I define REQUIRE(x) which is like assert(x) except that it throws an exception if the assertion fails in a release build.

Since a failed assertion indicates a bug, it should be treated seriously even in a Release build. When my code's performance matters, I will often use REQUIRE() for higher-level code and assert() for lower-level code that must run fast. I also use REQUIRE instead of assert if the failure condition may be caused by data passed in from code written by a third party, or by file corruption (optimally I would design the code specifically to be well behaved in case of file corruption, but we don't always have time to do that.)

They say you shouldn't show those assert messages to end-users because they won't understand them. So? End users may send you an email with a screen shot or some text of the error message, which helps you debug. If the user simply says "it crashed", you have less ability to fix it. It would be better to send the assertion-failure messages to yourself automatically over the internet, but that only works if the user has internet access and you can get their permission.

share|improve this answer
add comment

Unless profiling shows that the assertions are causing performance problems, I say they should stay in the production release as well.

However, I think this also requires that you handle assertion failures somewhat gracefully. For example, they should result in a general type of dialog with the option of (automatically) reporting the issue to the developers, and not just quit or crash the program. Also, you should be careful not to use assertions for conditions that you actually do allow, but possibly don't like or consider unwanted. Those conditions should be handled by other parts of the code.

share|improve this answer
add comment

If you want to keep them replace them with error handling. Nothing worse than a program just disappearing. I see nothing wrong with treating certain errors as serious bugs, but they should be directed to a section of your program that is equipped to deal with them by collecting data, logging it, and informing the user that your app has had some unwanted condition and is exiting.

share|improve this answer
add comment

Our database server software contains both production and debug assertions. Debug assertions are just that -- they are removed in production code. Production assertions only happen if (a) some condition exists that should never exist and (b) it is not possible to reliably recover from this condition. A production assertion indicates that a bug in the software has been encountered or some kind of data corruption has occurred.

Since this is a database system and we are storing potentially enterprise-critical data, we do whatever we can to avoid corrupted data. If a condition exists that may cause us to store incorrect data, we immediately assert, rollback all transactions, and stop the server.

Having said that, we also try to avoid production assertions in performance-critical routines.

share|improve this answer
    
I would call your "production assertion" an "exception", and code it as such. –  DaveWalley Feb 25 at 23:02
    
You're probably right but the product was originally written in C. Even when we changed it to be C++ the compilers we used on some of our platforms didn't properly support exceptions. Most of the old code was not rewritten in C++ so these assertions are still used. –  Graeme Perrow Feb 26 at 0:24
add comment

If you're even thinking of leaving assertions on in production, you're probably thinking about them wrong. The whole point of assertions is that you can turn them off in production, because they are not a part of your solution. They are a development tool, used to verify that your assumptions are correct. But the time you go into production, you should already have confidence in your assumptions.

That said, there is one case where I will turn assertions on in production: If we encounter a reproducible bug in production that we're having a hard time reproducing in a test environment, it may be helpful to reproduce the bug with assertions turned on in production, to see if they provide useful information.

A more interesting question is this: In your testing phase, when do you turn assertions off?

share|improve this answer
    
I think that assertions should never be included in production code. assertions are NOT errors, they are designed for developers. Assertions should only live in test code. Having an app crash is because of and assertion fail unacceptable and sloppy development. Developers need to go the extra mile to handle errors gracefully. –  iksnae Jan 31 at 18:57
add comment

I rarely use assertions for anything other that compile time type checking. I would use an exception instead of an assertion just because most languages are built to handle them.

I offer an example

file = create-some-file();
_throwExceptionIf( file.exists() == false, "FILE DOES NOT EXIST");

against

file = create-some-file();
ASSERT(file.exists());

How would the application handle the assertion? I prefer the old try catch method of dealing with fatal errors.

share|improve this answer
    
Exceptions are for unusual situations that you expect to encounter in a working application, like in your example here. Assertions are for situations that you expect to never encounter. So, if you do encounter them, there must be a bug in your code. In your example, and exception is clearly the right approach. But assertions are still very useful to catch bugs. –  MiguelMunoz Feb 4 at 7:40
add comment

Most of the time, when i use assertion in java (the assert keyword) I automatically add some production codes after. According to the case, it can be a logging message, an exception... or nothing.

According to me, all your assertions are critical in dev release, not in production relase. Some of them must be kept, other must be discarded.

share|improve this answer
add comment

Provided they are handled just as any other error, I don't see a problem with it. Do bear in mind though that failed assertions in C, as with other languages, will just exit the program, and this isn't usually sufficient for production systems.

There are some exceptions - PHP, for instance, allows you to create a custom handler for assertion failures so that you can display custom errors, do detailed logging, etc. instead of just exiting.

share|improve this answer
add comment

@Carl Seleborf

First of all, I'm hoping that this kind of problem would have been caught in testing, but let's say it wasn't for whatever reason. The second advice works - use the assertion to log it and create an error state (throw an exception, return an error value, close the application). In fact, that truly sounds like an exceptional case. But it's been over a year since I've done any work with pointers and memory management, so take my thoughts with a grain of salt.

Of course, you might be right and the second piece of advice should be ignored and the first one followed.

share|improve this answer
add comment

I see asserts as in-line unit tests. Useful for a quick test while developing, but ultimately those assertions should be refactored out to be tested externally in unit tests.

share|improve this answer
    
Assert: State a fact or belief. They're not for testing (only), but for stating what you think is true (i.e., your assumptions), so that your program will not continue if your assumptions are wrong for some reason. For example, this is a valid use of assertions: assert(pow(1,0) < 1). It's not really an appropriate place for error checking, because if that's not true, then pretty much all of modern math is wrong, and... well, how would you even begin to handle that? Handling that incorrect assumption is outside the scope of the program; you take it on faith. But you verify, anyway. –  Lee Dec 25 '13 at 0:54
add comment

ASSERTIONS are not errors and should not be handled as errors. When an assertion is thrown, this means that there is a bug in your code or alternatively in the code calling your code.

There are a few points to avoid enabling assertions in production code: 1. You don't want your end user to see a message like "ASSERTION failed MyPrivateClass.cpp line 147. The end user is NOT you QA engineer. 2. ASSERTION might influence performance

However, there is one strong reason to leave assertions: ASSERTION might influence performance and timing, and sadly this sometimes matter (especially in embedded systems).

I tend to vote for leaving the assertion on in production code but making sure that these assertions print outs are not exposed to end user.

~Yitzik

share|improve this answer
    
No, assertions are for assumed facts. If our code returns 27 when it's assumed it will ALWAYS return 25, the problem could also be a bug in our physical assumptions about the universe: maybe those two bits switched to the 5 possible value, for the first time in the history of computing. The assertion is there to confirm that your code is still operating under the assumptions it was written for. If physics goes out the window, your code should notice, leave the drive alone and quit while it's ahead ;) But yes, it's not an error in the code, and what kind of error handling could you do? –  Lee Dec 25 '13 at 1:03
    
Allow my to refine my opinion: 1. Assertion do check our assumptions. If our assumptions our wrong, this means that there is a bug in OUR code. 2. Our code should not assert usage of our code. i.e. a function should not fail on assertion if something is wrong in the input from user. We will return error and user should handle (he can assert success) 3. I prefer leaving assertion in production - but behavior will probably be modified. I agree that there is no appropriate error handling. Failed assertion == bug.. but the system might re-init itself instead of stopping and waiting for reboot. –  Yitshak Yarom Dec 26 '13 at 7:21
    
it doesn't NECESSARILY mean that there's a bug. For instance, many of the projects I'm involved in come with a list of assumed facts in the documentation. Those assumptions are there to protect developers' code from being called buggy, when business people might have told them the wrong thing, or when no information is available from third parties about particular variables, for instance. Assertions can be used to verify that the program should / should not run, that third-party systems are correct, not just whether IT is correct. –  Lee Dec 29 '13 at 17:48
add comment

I find it best to handle all errors that are in scope, and use assertions for assumptions that we're asserting ARE true.

i.e., if your program is opening/reading/closing a file, then not being able to open the file is in scope -- it's a real possibility, which would be negligent to ignore, in other words. So, that should have error-checking code associated with it.

However, let's say your fopen() is documented as always returning a valid, open file handle. You open the file, and pass it to your readfile() function.

That readfile function, in this context, and probably according to its design specification, can pretty much assume it's going to get a valid file ptr. So, it would be wasteful to add error-handling code for the negative case, in such a simple program. However, it should at least document the assumption, somehow -- ensure somehow --- that this is actually the case, before continuing its execution. It should not ACTUALLY assume that will always be valid, in case it's called incorrectly, or it's copy/pasted into some other program, for example.

So, readfile() { assert(fptr != NULL); .. } is appropriate in this case, whilst full-blown error handling is not (ignoring the fact that actually reading the file would require some error handling system anyway).

And yes, those assertions should stay in production code, unless its absolutely necessary to disable them. Even then, you should probably disable them only within performance-critical sections.

share|improve this answer
add comment

I never keep them on in performance critical code.

share|improve this answer
add comment

An assertion is error, pure and simple and therefore should be handled like one.

Since an error should be handled in release mode then you don't really need assertions.

The main benefit I see for assertions is a conditional break - they are much easier to setup than drilling through VC's windows to setup something that takes 1 line of code.

share|improve this answer
    
Using asserts as conditional breakpoints is really annoying for several reasons. Most important one is that these asserts confuse other developers in the team - how would they know if it's an error when that assert fired or is it that someone left his conditional breakpoint into the code? –  lego Nov 9 '12 at 19:35
    
There wouldn't be if asserts weren't in the code in the first place. And if you were using them to monitor code only you would see them (unless you were checking them into the source tree). I've worked in places which has asserts for practically everything. Having to click about 60 times at the start of the program because the help documentation server is non-available gets tiresome very quickly. –  graham.reeds Nov 9 '12 at 23:33
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.