Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assisting in avoiding assert... always!

Tags:

c++

c

assert

api

In C and C++ assert is a very heavyweight routine, writing an error to stdout and terminating the program. In our application we have implemented a much more robust replacement for assert and given it its own macro. Every effort has been made to replace assert with our macro, however there are still many ways assert can be reintroduced (e.g., from internal third-party libraries, naïve injection, etc.)

Any suggestions on how we can reduce, limit or even eradicate uses of assert? The best answer will be one the compiler can catch for us so we don't have to babysit the code base as much as we do currently.

like image 701
fbrereto Avatar asked Dec 04 '09 00:12

fbrereto


4 Answers

I'm not sure I really understand the problem, actually. Asserts are only expensive if they go off, which is fine anyway, since you're now in an exception situation.

assert is only enabled in debug builds, so use the release build of a third-party library. But really, asserts shouldn't be going off every moment.

like image 143
GManNickG Avatar answered Nov 20 '22 11:11

GManNickG


It can be handy to improve upon the built-in assertion facility (to provide stack traces, core dumps, who knows). In that case, if you're having problems getting your developers to follow whatever standards you have (like "instead of assert() use SUPER_ASSERT()" or whatever), you can just put your own assert.h header in the include path ahead of the compiler's runtime directory of headers.

That'll pretty much guarantee that anyone using the standard assert() macro will get a compiler error or get your assertion functionality (depending on what you have your assert.h header do).

like image 45
Michael Burr Avatar answered Nov 20 '22 10:11

Michael Burr


It would depend (at least in part) on what you're changing. Assuming that you don't mind it printing out its normal message, and mostly want to get rid of it calling abort(), you could consider leaving assert() alone, and instead defining your own version of abort().

In theory, doing that isn't portable -- but in reality, abort() is a fairly normal function in the standard library, and if you link your own instead, you get its behavior. Sometimes (especially some Microsoft linkers) you have to do a bit of work to get the linker to cooperate in replacing their abort() with yours, but it's rarely very difficult.

like image 2
Jerry Coffin Avatar answered Nov 20 '22 12:11

Jerry Coffin


I think your question is totally valid. If you have implemented your own error handling you may want to:

  1. Always trigger asserts even in release builds.
  2. Implement better error reporting in case an assert triggers. You may want to send error reports or write to log files.

That being said, I don't see any solution that always works.

  • If you are lucky, the third-party libraries use ASSERT macros that you can redefine yourself as long as the file defining this macro has some sort of #pragma once or #ifndef __HEADERFILE_H__ #define __HEADERFILE_H__ provision against multiple inclusion. Include the header file separately, redefine ASSERT and you're good.

  • If they directly include assert.h or cassert you can only patch the code I guess. Make minimal code changes, save the changes as patch files and when you update the library hope that the patches still work. Add the patches to version control.

If this doesn't work, rethink the question if you really need internal asserts in third-party libraries. Ship release builds only, this gets rid of the asserts, and add your ASSERTs to check for correctness inside your code. Check for validity of return values. If such an ASSERT is triggered, you can still dive into the third-party code to see what caused the problem.

like image 2
Sebastian Avatar answered Nov 20 '22 11:11

Sebastian