Is VERIFY(...) a good practice in C++ coding?

12,448

Solution 1

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.

Solution 2

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.

Solution 3

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).

Share:
12,448
sevaxx
Author by

sevaxx

Updated on June 15, 2022

Comments

  • sevaxx
    sevaxx almost 2 years

    Also, how does it compare to throwing an exception when something goes wrong ?

  • Amber
    Amber about 14 years
    One useful difference is if you have "nitpicky" tests that take a while to run, you can put them in an ASSERT() and then not worry about performance losses in Release mode.
  • rvalue
    rvalue over 12 years
    Putting in a top-level exception handler for 'uncaught exceptions' has the drawback that when an uncaught exception occurs, the stack is destroyed up to the top-level handler; which will then do something completely uninteresting like say which exception has occurred, then as you say, exit the program anyway. Leaving it un-handled entirely gives the debugger the opportunity to stop the program at the std::terminate with the entire execution stack available and inspectable.
  • Cameron
    Cameron over 10 years
    You opion about debug mode checks being in release mode is well supported here too!