Is Assert Evil

Is assert evil?

No, there's nothing wrong with assert as long as you use it as intended.

That is, it's supposed to be for catching cases that "can't happen", during debugging, as opposed to normal error handling.

  • Assert: A failure in the program's logic itself.
  • Error Handling: An erroneous input or system state not due to a bug in the program.

Is using assert() in C++ bad practice?

Assertions are entirely appropriate in C++ code. Exceptions and other error handling mechanisms aren't really intended for the same thing as assertions.

Error handling is for when there's a potential for recovering or reporting an error nicely to the user. For example if there's an error trying to read an input file you may want to do something about that. Errors could result from bugs, but they could also simply be the appropriate output for a given input.

Assertions are for things like checking that an API's requirements are met when the API wouldn't normally be checked, or for checking things the developer believes he's guaranteed by construction. For example if an algorithm requires sorted input you wouldn't normally check that, but you might have an assertion to check it so that debug builds flag that kind of bug. An assertion should always indicate an incorrectly operating program.


If you're writing a program where an unclean shutdown could cause a problem then you may want to avoid assertions. Undefined behavior strictly in terms of the C++ language doesn't qualify as such a problem here, since hitting an assertion is probably already the result of undefined behavior, or the violation of some other requirement which could prevent some clean-up from working properly.

Also if you implement assertions in terms of an exception then it could potentially be caught and 'handled' even though this contradicts the very purpose of the assertion.

Is it evil to redefine assert?

Redefining a Standard macro is an ugly idea, and you can be sure the behaviour's technically undefined, but in the end macros are just source code substitutions and it's hard to see how it could cause problems, as long as the assertion causes your program to exit.

That said, your intended substitution may not be reliably used if any code in the translation unit after your definition itself redefines assert, which suggests a need for a specific order of includes etc. - damned fragile.

If your assert substitutes code that doesn't exit, you open up new problems. There are pathological edge cases where your ideas about throwing instead could fail, such as:

int f(int n)
{
try
{
assert(n != 0);
call_some_library_that_might_throw(n);
}
catch (...)
{
// ignore errors...
}
return 12 / n;
}

Above, a value of 0 for n starts crashing the application instead of stopping it with a sane error message: any explanation in the thrown message won't be seen.

I am with Andrei Alexandresciu in thinking that exceptions are the best known method to report errors in code that wants to be secure. (Because the programmer cannot forget to check an error return code.)

I don't recall Andrei saying quite that - do you have a quote? He's certainly thought very carefully about how to create objects that encourage reliable exception handling, but I've never heard/seen him suggest that a stop-the-program assert is inappropriate in certain cases. Assertions are a normal way of enforcing invariants - there's definitely a line to be drawn concerning which potential assertions can be continued from and which can't, but on one side of that line assertions continue to be useful.

The choice between returning an error value and using exceptions is the traditional ground for the kind of argument/preference you mention, as they're more legitimately alternatives.

If this is right ... if there is a phase change in error reporting, from exit(1)/signals/ to exceptions ... one still has the question of how to live with the legacy code.

As above, you shouldn't try to migrate all existing exit() / assert etc. to exceptions. In many cases, there will be no way to meaningfully continue processing, and throwing an exception just creates doubt about whether the issue will be recorded properly and lead to the intended termination.

And, overall - there are several error reporting schemes. If different libraries use different schemes, how make them live together.

Where that becomes a real issue, you'd generally select one approach and wrap the non-conforming libraries with a layer that provides the error handling you like.

Are assertions always bad?

We use a modified version of assert, as per JaredPar's comment, that acts like a contract. This version is compiled into the release code so there is a small size overhead, but disabled unless a diagnostics switch is set, such that performance overhead is minimized. Our assert handler in this instance can be set to disabled, silent mode (e.g. log to file), or noisy mode (e.g. display on screen with abort / ignore, where abort throws an exception).

We used automated regression testing as part of our pre-release testing, and asserts are hugely important here as they allow us to find potential internal errors that cannot be picked up at a GUI level, and may not be initially fatal at a user level. With automation, we can run the tests both with and without diagnostics, with little overhead other than the execution time, so we can also determine if the asserts are having any other side effects.

One thing to be careful of with asserts is side effects. For example, you might see something like assert(MyDatabasesIsOk()), which inadvertently corrects errors in the database. This is a bug, as asserts should never change the state of the running application.

What is the use of assert in Python?

The assert statement exists in almost every programming language. It has two main uses:

  1. It helps detect problems early in your program, where the cause is clear, rather than later when some other operation fails. A type error in Python, for example, can go through several layers of code before actually raising an Exception if not caught early on.

  2. It works as documentation for other developers reading the code, who see the assert and can confidently say that its condition holds from now on.

When you do...

assert condition

... you're telling the program to test that condition, and immediately trigger an error if the condition is false.

In Python, it's roughly equivalent to this:

if not condition:
raise AssertionError()

Try it in the Python shell:

>>> assert True # nothing happens
>>> assert False
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError

Assertions can include an optional message, and you can disable them when running the interpreter.

To print a message if the assertion fails:

assert False, "Oh no! This assertion failed!"

Do not use parenthesis to call assert like a function. It is a statement. If you do assert(condition, message) you'll be running the assert with a (condition, message) tuple as first parameter.

As for disabling them, when running python in optimized mode, where __debug__ is False, assert statements will be ignored. Just pass the -O flag:

python -O script.py

See here for the relevant documentation.

Is it bad practice to use assert to verify assumptions about arguments in python?

The answer to the original question ("Is it bad practice to use assert to verify internal assumptions in python?") is decidedly no. That's the one thing everyone agrees assertions are good for. But what you describe in the question isn't validation of an internal assumption: It's validation of external inputs. A TypeError, a ValueError, another builtin exception (or possibly a custom exception, though one should be conservative with those) gives much more useful feedback to users of the API. What's worse, assertions may be (and, in some environments, usually are) removed completely, meaning your code will silently do the wrong thing.

What does the Java assert keyword do, and when should it be used?

Assertions (by way of the assert keyword) were added in Java 1.4. They are used to verify the correctness of an invariant in the code. They should never be triggered in production code, and are indicative of a bug or misuse of a code path. They can be activated at run-time by way of the -ea option on the java command, but are not turned on by default.

An example:

public Foo acquireFoo(int id) {
Foo result = null;
if (id > 50) {
result = fooService.read(id);
} else {
result = new Foo(id);
}
assert result != null;

return result;
}

Is it good practice to use assert in Java?

The main reason assertions are not used is because they are not enabled by default. Therefore if you have a condition that is important enough to require an assertion you can't rely on assertions being enabled to get the job done.

As other answers have correctly stated they're designed for development-time testing and debugging because they cost nothing if assertions are disabled in production. I think it's better to create explicit tests in your testing framework (e.g. a unit test for edge conditions) than rely on someone enabling assertions while testing.

However a good example I've seen for using assertions is checking private method arguments. Since you control the access to those methods you can check that your own class is using the method correctly while your public methods use more reliable argument checking techniques (annotations, if statements, 3rd-party libraries, etc). That way even if assertions are disabled your method should be protected but developers looking at the source code can see the preconditions for your method and turn assertions on for an extra safety net when working on that class.

Best practice for using assert?

To be able to automatically throw an error when x become less than zero throughout the function. You can use class descriptors. Here is an example:

class LessThanZeroException(Exception):
pass

class variable(object):
def __init__(self, value=0):
self.__x = value

def __set__(self, obj, value):
if value < 0:
raise LessThanZeroException('x is less than zero')

self.__x = value

def __get__(self, obj, objType):
return self.__x

class MyClass(object):
x = variable()

>>> m = MyClass()
>>> m.x = 10
>>> m.x -= 20
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "my.py", line 7, in __set__
raise LessThanZeroException('x is less than zero')
LessThanZeroException: x is less than zero

What is the assert function?

assert will terminate the program (usually with a message quoting the assert statement) if its argument turns out to be false. It's commonly used during debugging to make the program fail more obviously if an unexpected condition occurs.

For example:

assert(length >= 0);  // die if length is negative.

You can also add a more informative message to be displayed if it fails like so:

assert(length >= 0 && "Whoops, length can't possibly be negative! (didn't we just check 10 lines ago?) Tell jsmith");

Or else like this:

assert(("Length can't possibly be negative! Tell jsmith", length >= 0));

When you're doing a release (non-debug) build, you can also remove the overhead of evaluating assert statements by defining the NDEBUG macro, usually with a compiler switch. The corollary of this is that your program should never rely on the assert macro running.

// BAD
assert(x++);

// GOOD
assert(x);
x++;

// Watch out! Depends on the function:
assert(foo());

// Here's a safer way:
int ret = foo();
assert(ret);

From the combination of the program calling abort() and not being guaranteed to do anything, asserts should only be used to test things that the developer has assumed rather than, for example, the user entering a number rather than a letter (which should be handled by other means).



Related Topics



Leave a reply



Submit