Also, how does it compare to throwing an exception when something goes wrong ?
The question looks simple, but hides a huge subject : dealing with errors.
Summarilly I would say assert and verify are tools to use in developement process while exceptions and system calls error checking are normal parts of production code to deal with runtime errors.
Assertions (it applies to assert and verify) are tools mostly used in defensive programming style. Their main goal is to protect against cases that should never occurs and programmer has no idea of what to do if that happen. Usually it is used to check for programming errors. When the impossible happen while debugging a program you usually want to detect and report it as fast as possible. It will simplify error correction. You can use it with some condition or even as assert(false)
typically to check that a branch of a switch is never caught.
I mostly use assertions when dealing with third-party code whose behavior I'm unsure. For checking behavior of my own code code under development I usually prefer unit testing.
Now, as Schroëdinger taught us, mesures change things. You may sometime have code that works in debug mode when assert is enabled and stop working in release mode. It usually is the symptom of an hidden bug inside the assertion condition (side effect, time sensitive code). Verify minimize this kind of risk, but it can be considered a bad practice, like sweeping dust behind the carpet.
You can also use verify for fast coding as scafolding for places where you didn't set up a real error handling yet. I do not believe you should let any verify in production code.
Exceptions are a normal part of program control flow. Most often they are used to deal with errors, but it's not their only possible use (those who use other languages like python will know what I'm speaking about). Neither should they be considered as the only error management tool. When not wrapped in a c++ aware library, system calls still return an error code instead of raising an Exception.
As a rule of thumb Exceptions should be caught by the nearest object that is able to handle them sensibly.
Also not all exceptions should be considered as fatal errors and stop program. Imagine you are dealing with a network video streaming library returning error cases through exceptions. It the library throw an Exception warning that a frame was dropped, you usually don't want to stop the program but just get it ready for the next frame.
Even when the best thing to do is to stop the program you should not let exception do it for you (and you have even less reason to use assert for that purpose in production code). There should always exist a top level exception handler for that purpose that makes explicit calls to exit() of like. Not doing it merely show that the programmer didn't care about what may happen and probably didn't thought about it.
In Visual C++, there are two macros for checking conditions: ASSERT
and VERIFY
.
In debug mode, they both behave the same: that is, they both evaluate their argunment and if the result is 0, they both halt the program with an assertion failure dialog box.
The difference lies in release mode. In release, mode, ASSERT
is completely removed from the program: it doesn't evaluate it's expression at all. VERIFY
, on the other hand, still evaluates the expression, it just ignores the result.
Personally, my opinion is that if the check is valuable in debug mode then it's still valuable in release mode as well and you probably shouldn't use either of them. Just do the test and throw an exception (or use a custom macro that expands to assert()
in debug mode and an exception in release mode).
VERIFY()
serves the same purpose as ASSERT()
(or the standard library assert()
) - to let you catch things that really shouldn't ever™ be happening (i.e. a true code bug, something that should be fixed before release). The kinds of things that if for some reason the expression is false, there's no point to continuing because something is horribly, horribly wrong.
This is reflected in the fact that VERIFY()
only stops the program on a false evaluation when compiling in Debug mode - in Release mode, it's transparent. The difference between VERIFY()
and ASSERT()
is that VERIFY()
will still evaluate the expression in Release mode, it simply won't care about the result - whereas ASSERT()
is completely removed from the program when compiling in Release mode and thus any side-effects of the expression within it won't take place.
Exceptions are more useful for things that might go wrong, but can be recovered from, since exceptions can be handled by other parts of the program.
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