3

I'm currently using the following statement to get assert and printf to work together, is there any better way to do this?

#define ASSERT(x) for(; !(x); assert(x))
#define ALLOC_CHECK(x, ...) ASSERT(x) printf(__VA_ARGS__ "\n");
ALLOC_CHECK(ptr != NULL, "Pointer not initialized");
user3666471
  • 907
  • 11
  • 24

2 Answers2

6

You don't need to whip up your own assert() variant, you can just include an error message in the assert itself:

assert(someCondition && "Internal error: ... . Please report this bug.");

Since the assert() macro prints its argument on failure, it will also print your string.

cmaster - reinstate monica
  • 38,891
  • 9
  • 62
  • 106
  • With the above method, I can't use `printf` with anything like `%d` correct? – user3666471 Dec 20 '14 at 10:30
  • That is true, but you can't do that with your approach either, because you try to append `"\n"` to the last argument of the macro. Anyway, as dasblinkenlight says, assertions are to detect broken assumptions only, not to provide a lot of debugging information. – cmaster - reinstate monica Dec 20 '14 at 10:34
  • I usually include say the size of an array or linked list in the `printf` information when I `assert` on the index bounds. Is that not advisable? – user3666471 Dec 20 '14 at 10:41
  • I don't know the context, but it shouldn't really make a difference. If you assert on `assert(i < size);`, you get the exact line that fails, and the exact condition that fails. Usually this will point you directly to the line of code that should have avoided failing the assert, the concrete values are of little value. Yes, it might be nice to have this additional information, I just don't think it's worth the effort. After all, you are never expecting an assertion to fail. – cmaster - reinstate monica Dec 20 '14 at 10:55
3

There is a logical issue with your use of assert: one should not use it for checking conditions that may be false, assuming that the program is written correctly.

The reason the asserts exist in the first place is to let you make statements in your program about your assumptions about the state of the program. Triggering an assert should indicate an error in your program's logic, and nothing else. In particular, it should not be used to detect a situation when you run out of memory, which is something that could reasonably happen even when your program is 100% correct.

When you write, for example,

int i = getIndex();
assert(i > 0);

you tell the compiler and the readers of your code that your algorithm is such that getIndex() could not possibly return a negative number. By using an assert you say that if it does, then there is an error in your code. Using asserts to check runtime conditions would be a misuse of that feature.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • What would be the best way to tell the user not to give me a `NULL` pointer without using an `assert` on it? Just return with a `-1` or similar? – user3666471 Dec 20 '14 at 10:39
  • @user3666471 Unfortunately, C does not have a good way of telling the user that he had given you an invalid parameter in a call. [This question](http://stackoverflow.com/q/385975/335858) discusses some possibilities, but all of them require the caller to pay attention to the return value. – Sergey Kalinichenko Dec 20 '14 at 10:47
  • @user3666471: Why not use an `assert`? – mafso Dec 20 '14 at 11:22
  • @mafso: That's what I'm using now, I wanted to know if there was a more cleaner way. – user3666471 Dec 20 '14 at 11:34