1

Is it possible to write a message on assert error?

For example, using #include <assert.h>, I can only write:

void foo(int a, int b) {
  assert (a != b);
}

However, on an error I want to see the value of a and b. How can I do that?

aymericbeaumet
  • 6,853
  • 2
  • 37
  • 50
mahmood
  • 23,197
  • 49
  • 147
  • 242

3 Answers3

8

I usually simply use assert(a != b && "This is my error message"). This works because char* can be converted to bool and that it never will be false (since the address is not 0).

larsmoa
  • 12,604
  • 8
  • 62
  • 85
7

assert is just a preprocessor macro, that if the condition fails calls abort. You can easily make your own with a simple if statement, and if it fails print the values and call abort just like assert:

void foo(int a, int b)
{
    if (a != b)
    {
        std::cerr << "My own assertion failed: a = " << a << ", b = " << b << '\n';
        abort();
    }

    /* ... */
}

However, as you are using C++ you should probably thrown an exception instead, probably std::logic_error:

void foo(int a, int b)
{
    if (a != b)
    {
        std::istringstream is;
        is << "Argument mismatch in `foo`: a = " << a << ", b = " << b;
        throw std::logic_error(is.str());
    }

    /* ... */
}
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 2
    for an assert i think a #ifdef DEBUG should also be used – user1810087 May 27 '13 at 15:22
  • 1
    That's true, but the correct macro is `NDEBUG`, with the inverted meaning. That said, suggesting to replace an assertion with an exception is a bad idea. One is for runtime errors that you can handle and recover from. The other is for programming errors that an inconsistent internal state, where you should dump core and abort. – Ulrich Eckhardt May 27 '13 at 17:39
1

It is possible to write your own assert macro which can break down an expression into subexpressions and print the values of each; but it requires a lot of code to support it, and the standard assert macro doesn't do that on any implementation I know of.

For an example of how to implement such a thing, see the CATCH test framework, in particular the implementation of the CHECK macro.

Alternatively, you could write macros or functions like ASSERT_EQUAL(a,b), giving each subexpression as a separate argument.

Or you might write your own error-handling code without assert

if (a == b) {
    throw std::runtime_error("foo: a(" + std::to_string(a) + ") must not equal b");
}
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • Marco is possible, but I don't want to use that. – mahmood May 27 '13 at 15:20
  • 1
    @mahmood: You could probably implement it as a function, but then you'd lose the `__FILE__` and `__LINE__` macros telling you where the assertion is in the code, and the ability to capture the expression as a string. – Mike Seymour May 27 '13 at 15:24