Why should I use asserts?

C++PerformanceAssertions

C++ Problem Overview


I never got the idea of asserts -- why should you ever use them?

I mean, let's say I were a formula driver and all the asserts were things like security belt, helmet, etc.

The tests (in debug) were all okay, but now we want to do racing (release)! Should we drop all security, because there were no issues while testing?

I will never ever remove them. I think most of the guys that claim that removing something comparable to asserts never profiled their code or the asserts were absolute displaced. I've never seen any real performance advantage especially regarding the 80 / 20 rule.

So, am I missing the point somehow, or could anybody tell me, why I should use asserts? By the way, I'm using unit tests.

C++ Solutions


Solution 1 - C++

First, the performance difference can be huge. In one project our asserts literally caused a 3x slowdown. But they helped us uncover some really pesky bugs.

Which is exactly the point.

Asserts are there to help you catch bugs. And because they are removed in release builds, we can afford to put a lot of them in without worrying about performance. If you're not there to actually act on any failed assertions, they become worthless, so we might as well remove them.

Even catching the error and throwing an exception isn't really a solution. The program logic is flawed, and even if we handle the exception, the program is still broken.

What asserts basically boil down to is "Why bother catching errors you can't handle?"

Some errors must be caught during development. If they slip past testing and into the release build used by a customer, the program is just broken, and no amount of runtime error-checking is going to fix it.

> I never got the idea of asserts -- why should you ever use them? > > I mean, let's say I were a formula driver and all the asserts were things like security belt, helmet, etc.

Yes, that's a good example of when not to use an assert. These are things that might actually go wrong at runtime, and which need to be checked. Your formula one driver might forget some security precaution, and if he does, we want to halt the whole thing before anyone gets hurt.

But what about the check to see that the engine is installed? Do we need to check that during the race?

Of course not. If we get into the race without an engine, we're screwed, and even if we detect the error, it's too late to do anything about it.

Instead, this is an error that must be caught during development or not at all. If the designers forget to put an engine in their car, they need to detect this error during development. That's an assert. It's relevant to the developers during development, but afterwards, the error must not exist, and if it does, there's nothing we can do.

That's basically the difference. An exception is there to help the user, by handling errors that can be handled.

An assert is there to help you, by alerting you to errors that must never occur in the first place, that must be fixed before the product can be shipped. Errors that do not depend on user input, but on your code doing what it is supposed to do.

The square root of four must never evaluate to three. The error is simply impossible. If it does occur, your program logic is just broken. It doesn't matter how much error handling we wrap around it, it's something that must be caught during development or not at all. If we used exception handling to check for this error and handle it, what is the exception going to do? Tell the user "the program is fundamentally broken. Don't ever use it"?

An email from the developer could have achieved that. Why bother building it into the program code? That's an example of a problem that simply must not occur. If it does, we have to go back and fix the program. No other form of error handling is possible.

But some errors, like being unable to open a file for reading, are possible. Even though it might be a bad thing if it happens, we have to accept that it can happen. So we need to handle it if it does.

Asserts are for catching the errors that can't possibly happen.

Solution 2 - C++

Andrew Koenig used to have a good philosophical discussion over the usage of exceptions and assertions in shipping code. In the end, you're guarding against doing wild things when the program is in an irreparably broken state.

> I believe, therefore, that when a > program discovers something that is > irrefutably wrong with its internal > state, it is better off terminating at > once, rather than giving its caller > the opportunity to pretend that > nothing is wrong. > > If you like, I think that exceptions > should be reserved for situations in > which it is possible to do something > sensible after catching the exception. > When you discover a condition that you > thought was impossible, it's hard to > say much about what might happen > afterward.

Solution 3 - C++

From Code Complete 2: "Use error-handling for conditions you expect to occur; use assertions for conditions that should never occur."

A commonly-cited example is checking for zero in the denominator before a division.

You're expected to strip the assertions out of production code. They are in there during development to help you catch mistakes.

Unit tests are not a replacement for assertions.

Solution 4 - C++

Because they make debugging easier.

The time consuming part of debugging is tracing a problem from the symptom you first notice back to the error in the code. Well written assertions will make the symptom you notice much closer to the actual code problem.

A very simple example would be a bug where you index past the end of an array and cause memory corruption which eventually causes a crash. It can take a long time to trace back from the crash to the offending index operation. However, if you have an assertion next to that index operation that checks your index, then your program will fail right next to the error, so you'll be able to find the problem quickly.

Solution 5 - C++

It's a controversial subject. Many people, like myself, do actually prefer to leave them on in production code. If your program is going to go into the weeds anyway, you might as well have the assertion in there so your customer can at least give you the line number and filename (or whatever information or action you configure the assert to do). If you left the assertion out, all the customer could report to you was "it crashed".

This means you probably should not do expensive operations in your assert checks, or at least profile to see if they are going to cause performance problems.

Solution 6 - C++

They enable you to test your assumptions. For example, let's say that you wanted to calculate speed. You would probably want to assert that your calculation is less than the speed of light.

Assertions are for development, to make sure you don't mess up.

Solution 7 - C++

From your post, it sounds like you are not disagreeing with the idea of using assertions, but rather the idea of having assertions in debug and not having them active in production.

The reason for this is that when debugging, you might want the process to fail catastrophically -- i.e. throw an exception and quit, so that the error can be addressed. In production, this could affect your entire system, and the error condition could occur only for a very few cases. So, in production you would probably want to log the error, but keep the process running.

Using assertions lets you change the behavior between debug and release.

I agree with you that the assertions should not just be silenced in production code -- many errors are not exposed in test environments and it is important to know when assertions fail in production.

Solution 8 - C++

Assertions are invaluable while refactoring I think. If you want to replace alogrihm1() with algorithm2(), you could have them both and assert on the results being equal. You can then gradually phase out the algorithm1()

Asserts are also good for some changes that you might make quickly, but are not too sure of in the context of the state of the system. Setting up asserts for the assumptions you make, would quickly help you to point out the problem, if any.

It is debatable whether asserts should be stripped via using macros or the like in release, but that's what has been done in the projects I have worked on so far.

Solution 9 - C++

In Code complete is a section that says something like. Every time you write an if without any else you are maybe missing something.

It is like this code

int i = 1
i = i++ 

The common programmer will never think about what happens if i is negative in later code. There is the slightly chance of your code producing an overflow and languages like java will jump from max int to min int and you get a very big negative number. This are all the cases you normally say. Uh this will never ever happen. But what is your program doing if it happens? So if you know that there is something that you think will never happen test for it or against it and put an assert false in the else clause that will never happen instead of don't program the else statement. In this way your program should crash completely in the moment you aren't sure any more what it is doing. In production code there should be something different from rather crashing something like informing the user, the maintainer and then exiting.

Another use of assertions is contract driven design. You specify an contract with your interface and depending on your place in the program you assert your input but much more importing you are asserting your output two.

I agree with you that disabled assertions in production code make assertions rather useless. And the default assertions off in case of the java vm is a hazard in my opinion.

Solution 10 - C++

In many project I've worked in, assertions were done with a custom macro that had different behaviour in Debug and Release.

In Debug, if the condition is false the debugger is started at that point in the code.

In Release, the error is written to a log file, a warning given to the user, and then the system attempts to save unsaved data. Being in an unknown state, this may fail, but it's worth trying.

Solution 11 - C++

Asserts should only be used to check conditions during development that are not needed during release.

Here is a really simple example of how assertion can be used in development.

A(char* p)
{
    if(p == NULL)
        throw exception;

    B(p);
    C(p);

}

B(char* p)
{
    assert(p != NULL);
    D(p);
    do stuff;
}

C(char* p)
{
    assert(p != NULL);
    D(p);
    do stuff;
}

D(char* p)
{
    assert(p != NULL);
    do stuff;
}

Instead of calling "if(p == NULL) throw exception;" 5 times, you just call it once so you already know it's not NULL upon entering B(), C(), and D(). Otherwise, an assertion will exit in the development phase because you "changed the code!" not because of a "user's input".

This can make the code run a lot faster in the release version because all you have to do is invoke gcc with "-DNDEBUG" so all of the assertions will not be compiled and all the "unnecessary checks" will be removed in the executable.

Solution 12 - C++

Just don't use Assertions when you don't want. There is nothing wrong not to use it.

Assertion is only helpful when a test case in debug mode actually hit it. Many times it doesn't hit at all, depends on quality of your test cases. Assertion is used when you try to verify an assumption, so you got what you asked for, you hardly break your assumption during test. That's why you assume it in first place isn't it. Yet there are endless number of "expected impossible" cases that really don't hit your assertion during debug, but somehow still hit in production which have assertion disabled. If you rely on assertion during debug then you most likely end up having some unexpected thing happen in production that even your assertion didn't catch.

Your program should be designed in a strategic way, so that even unexpected matter happen or your test cases didn't cover, a problem is still handled in a defined way, or produce meaningful diagnostic info.

You can use assertion to help troubleshooting, but it is not helpful if you want to prevent problem from happening in first place. The reason is that you can't prevent or handle a niche problem if you assume it won't happen in production (you disable assertion in Production). Good software should catch obvious errors (assertion helps), as well as niche errors (assertion probably won't help).

Many people will tell you a standard version of what is assertion supposed to do. What assertion is good for etc. But please justify by your own experience if it is really helpful or not. Assertion is not scientific proven or golden rule, it is just a practice of many people. You should decide to adopt it or not by yourself.

Solution 13 - C++

I've written code where the assertions demonstrably affected performance when enabled. Checking the pre- and post-conditions of maths functions used in tight loops by your graphics code, for example (square root function squares its result and compares it against the input, etc). Sure, it's on the order of a few percentage points, but I've written code that needed those few points.

More importantly, I've written code where the assertions made a tens-of-percentage-points difference to the size of the code. When memory footprint is an issue, asserts in release code are probably an unacceptable extravagance.

Solution 14 - C++

I use it mostly for tests during development. For instance, here is the smoke test of my utf-8 library Whenever I make a change in the library code I run the tests and if a bug is introduced an assert will trigger. Of course, I could have used a full-blown unit test framework, but for my purposes asserts are just fine.

Solution 15 - C++

Can't resist quoting "The indispensable Calvin and Hobbes" p. 180:

Before going down a steep hill like this, one should always give his sled a safety check.
Right.
Seat belts ? None.
Signals ? None.
Brakes ? None.
Steering ? None.
WHEEEEEE

Solution 16 - C++

Assertion should be used when you do something like this

a = set()
a.add('hello')
assert 'hello' in a

or

a = 1;
assert a == 1; // if ram corruption happened and flipped the bit, this is the time to assert

As for exceptions, it's something you programmatically deal with:

while True:
  try:
    data = open('sample.file').read()
    break // successfully read
  except IOError:
    // disk read fail from time to time.. so retry
    pass

Most of the time it's safer to restart your application when assert happens, because you don't want to deal with impossible cases. But when the expected case happens (expected errors (most of the time from black-box clients, network calls, etc..) the exceptions should be used.

Solution 17 - C++

Assertion should be used for anticipating error in the way a programmer is using an API/function/class/whatever. These bugs need to be fixed quickly at debug time.

For everything else, throw an exception.

Solution 18 - C++

For other answers to this question

> assert() macro is used to test the conditions or assumptions that > should not occur in a program. For example, the array index should > always be > 0. Another assumption can be 2+2 == 3+1. > > So using assert () we can test such assumptions and as long as they > evaluate to true, our program runs normally. When they are false, the > program is terminated.

more here https://www.softwaretestinghelp.com/assert-in-cpp/

Solution 19 - C++

I NEVER use assertion in my code, I hate them with passion. I understand the need for error checking and handling but to prevent an error that would crash your program by crashing your program yourself .... frankly I do not see the advantage.

Also leave one assertion in your code and murphy's law will ensure that it will, eventually, crash your program. I much prefer checking the data before I do processing with it and throw the appropriate exception so it is handled much like any other exceptional states or operation. This in my experience yielded software that was much more stable in the long run with deterministic behavior from the user's stand point.

You as a software engineer will know what to do when your program asserts out, most users will just get scared they broke something and will end up not using your software. So unless you are developing for engineers (which is quite possible) and even then...

From a usability stand point asserts are horrible, even if they are not "supposed" to happen we all know that eventually it will...


Ok... From all the comment and fire I am getting here I think I need to further explain my point of view because it is clearly not understood.

I did not say I was not checking for exceptions, weird values or just plain wrong states, I just said I did not use assertions because of the horrible way they tent to close the system from a end-user's perspective. Also most modern languages provide another, type-safe way to handle these situations, whey then would I use assert when a perfectly good exception would do the trick, and quite nicely so too.

In most production code I have seen out there I noticed mainly two ways to deal with this, buttering asserts all over the code and then leave a good bunch in production. This has the infuriating tendency to just close the application to the user, I have yet to see an Assert gracefully fail a system.... it just fails it ... boom... gone... end user just saying "WTF is a assertion failed error at address 0x330291ff!!!"

The other way, even worst if you ask me, was to just catch whatever was thrown and hide it under the carpet (ever seen these dreadful try-catch with empty braces !!)

NEITHER WAY will work to get a good stable system. Sure you can use asserts in your beta code and remove them all in your production code... but why the hell would you remove your safety nets because it is production. I would be very surprised that all these checks would cripple your system's performances.

Build yourself a good exception handling scheme and .. by god... LEAVE IT THERE, you will get much more meaningful information our of your system and if done appropriately always in context than having some deep library throwing asserts because something is missing.

This is especially true when creating libraries... to think you, the creator of the library, can decide when to bring down the whole system because something went wrong in the data that was thrown at you is incredibly selfish and narrow minded. Let the user of your library decide what is sufficiently important that it should warrant emergency failure.

so no... I do not use asserts... I use exceptions

And yes... usually the code that fails in production has rarely my name on top.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionjanView Question on Stackoverflow
Solution 1 - C++jalfView Answer on Stackoverflow
Solution 2 - C++cdlearyView Answer on Stackoverflow
Solution 3 - C++NosrednaView Answer on Stackoverflow
Solution 4 - C++David NormanView Answer on Stackoverflow
Solution 5 - C++Brian NealView Answer on Stackoverflow
Solution 6 - C++geowa4View Answer on Stackoverflow
Solution 7 - C++Larry WatanabeView Answer on Stackoverflow
Solution 8 - C++psquareView Answer on Stackoverflow
Solution 9 - C++JanuszView Answer on Stackoverflow
Solution 10 - C++Pete KirkhamView Answer on Stackoverflow
Solution 11 - C++Jeremiah DicharryView Answer on Stackoverflow
Solution 12 - C++Chris TsangView Answer on Stackoverflow
Solution 13 - C++Steve JessopView Answer on Stackoverflow
Solution 14 - C++Nemanja TrifunovicView Answer on Stackoverflow
Solution 15 - C++denisView Answer on Stackoverflow
Solution 16 - C++vtlinhView Answer on Stackoverflow
Solution 17 - C++balajeercView Answer on Stackoverflow
Solution 18 - C++PeterView Answer on Stackoverflow
Solution 19 - C++NewtopianView Answer on Stackoverflow