Show Lecture.Assertions as a slide show.
CS253 Assertions
Assertion failure!
You’re out of here!
Overview
There are two sorts of assertions in C++:
They both come from <cassert>
.
assert()
is a preprocessor macro that is, essentially:
void assert(bool condition) {
if (!condition) {
cerr << "assertion failed: name-of-condition\n"
abort();
}
}
- It’s a runtime condition.
- It has to be in executable code.
- What would be a place that’s not in executable code?
#include <cassert>
#include <string>
void delete_file(const std::string &fname) {
assert(!fname.empty());
remove(fname.c_str());
}
int main() {
delete_file("tempfile");
delete_file("");
}
a.out: c.cc:5: void delete_file(const string&): Assertion `!fname.empty()' failed.
SIGABRT: Aborted
- Do not use
assert()
for dealing with user errors.
- Only use it for “impossible” circumstances:
- Make sure that a function argument, representing a size, is positive.
- Make sure that a pointer argument isn’t null.
- etc.
Disabling assertions
If you’re concerned about the run-time cost of assertions:
- You’re just worrying without data. Knock it off.
- The preprocessor symbol
NDEBUG
,
which stands for no debugging,
disables assertions, when defined.
- Use #define
NDEBUG
or g++ -DNDEBUG
to define NDEBUG
.
- Make sure that your assertions have no side effects.
Your code must produce the same results even if the assertions
are all disabled.
Avoid side effects
The assert()
expression must not have side effects:
% cat ~cs253/Example/assert.cc
#include <iostream>
#include <cassert>
using namespace std;
int main() {
int n = 42;
assert(++n > 10); // 🦡
cout << n << '\n';
}
% g++ -Wall ~cs253/Example/assert.cc
% ./a.out
43
% g++ -DNDEBUG -Wall ~cs253/Example/assert.cc
% ./a.out
42
static_assert
is like assert()
, but:
- It’s a compile-time test. It “executes” at compile time.
- It has zero run-time cost, because … compile-time.
- It fails like a syntax error fails.
- It doesn’t have to be in executable code.
- might be in a class definition
- might be outside of any function or class
- It takes two arguments:
- a condition
- an error message string (optional starting in C++17)
#include <iostream>
#include <cassert>
static_assert(-1 >> 1 == -1, "right shift must preserve sign");
int main() {
std::cout << "Hello, world!\n";
static_assert(sizeof(char)==1, "char must be 8 bits");
return 0;
}
static_assert(sizeof(int)==3, "int must be 24 bits");
c.cc:12: error: static assertion failed: int must be 24 bits