C General Question - FreeBSD's approach to assert(x != NULL)

C:
assert(x != NULL);

Am I correct in thinking that the above statement will halt the execution of a compiled binary if x == NULL when the assert code is called?

Does it call any deconstructors, or is it a hard (as in kill -9) approach?

Edit: Also, what is the good practice within FreeBSD base with regards to using assert in code in a production enviroment rather than an if + error handling?

Edit 2: The code is C, and not C++ as originally tagged. Sorry for any confusion.

Thanks,
James
 
First of all, assert(3) is C, not C++. This manpage should also answer all your questions. In a nutshell, it's a debugging tool only, will forcefully abort(3) the program without any cleanup (which would be caught by an attached debugger, so you could start analyzing program state right away), and must never be used to check for anything that's expected to happen eventually. An unmet assertion must correlate to a bug in your program.

It's good practice to create release builds with NDEBUG defined, which will remove all assertion checking code.
 
Many thanks. The man pages you referenced are brilliant, and it explains it well.

Again, excuse my ignorance, but is NDEBUG a default option in the GENERIC kernel when building world, from say a fresh git clone of the github src tree please?
 
Many thanks. The man pages you referenced are brilliant, and it explains it well.

Again, excuse my ignorance, but is NDEBUG a default option in the GENERIC kernel when building world, from say a fresh git clone of the github src tree please?

The main branch (FreeBSD-current) defaults to have a debug kernel. All other official branches do not.
 
is NDEBUG a default option in the GENERIC kernel when building world
The kernel configuration has nothing to do with building world. That said, just browse the code, FreeBSD's build systems adds some NDEBUG defines in many places. You don't want assertions in code used in production ...
 
`assert` and `NDEBUG` are defined in the ISO C standard. It's in section 7.2 of the draft of C23 that I have.

The C standard is more oriented towards userland applications. It says that if an assert fires then it writes an error message including the file and line number to stderr and then calls abort().

abort() will result in SIGABRT being raised. It is possible to handle SIGABRT (unlike SIGKILL). Assuming that you don't handle SIGABRT then destructors do not get called and neither do any atexit functions.

See
 
Separate reply for good practice.

I'm only going to talk about non-recoverable errors.

When something has gone hopelessly wrong then firing an assert that produces a clear and easy to debug message is a good thing. I work with a codebase that does that and I think that it is much better for it.

I've also worked with codebases where the culture was to just try to hide errors. That can be a nighmare. When something goes wrong there are two possible outcomes
  • The error isn't detected and you enter into the twilight zone of Undefined Behaviour. Anything can happen. If you are lucky you get a quick crash. If you're not lucky you get incorrect results that are hard to reproduce.
  • The error is detected and the application goes into "pass the buck mode". If you are lucky the error gets ignored but you do get a warning. If you are not lucky the error either gets ignored or if the error can't be ignored the buck gets passed around multiple times making it extra difficult to trace back the source of the error to the manifestation.
 
Edit 2: The code is C [...]
Perhaps you may also like Modern C - Jens Gustedt, where:
[assert] is helpful during the debugging phase, where it can lead you to spots where you make false assumptions about the values of variables.

Takeaway 1.8.7.4 Use as many assert s as you can to confirm runtime properties.

As mentioned, NDEBUG inhibits the evaluation of the expression and the call to abort.
Please use it to reduce overhead.

Takeaway 1.8.7.5 In production compilations, use NDEBUG to switch off all assert
 
Back
Top