Defensive Programming with Assertions

How can I use assertions to practice "defensive programming" and make my code more robust?

Defensive programming is a style of programming that anticipates potential errors and takes steps to prevent or mitigate them. Assertions are a key tool in defensive programming, as they allow you to express and validate assumptions about your code.

Here are some ways to use assertions for defensive programming:

Example 1: Check function preconditions:

int strlen(const char* str) {
  assert(str != nullptr);// ...
}

Example 2: Validate function postconditions:

int pop(std::stack<int>& s) {
  assert(!s.empty());
  int top = s.top();
  s.pop();
  assert(top == s.top());
  return top;
}

Example 3: Verify loop invariants:

int sum(const std::vector<int>& v) {
  int total = 0;
  for (size_t i = 0; i < v.size(); ++i) {
    total += v[i];
    assert(total >= 0);
  }
  return total;
}

Example 4: Check switch cases and if-else chains:

char to_lower(char c) {
  switch (c) {
    case 'A': return 'a';
    case 'B': return 'b';
// ...
    default:
      assert(false && "Invalid character");
  }
}

Example 5: Test user input:

void save_preferences(int pref) {
  assert(pref >= 0 && pref < 10);// ...
}

Some tips for effective defensive programming with assertions:

  • Be liberal with assertions. It's better to have too many than too few.
  • Assert as close to the source of the error as possible.
  • Don't use assertions as a substitute for error handling. Assertions are for detecting bugs, not for expected error conditions.
  • Leave assertions enabled in debug builds to catch problems early.
  • Consider writing unit tests to exercise assertions and edge cases.

Remember, the goal of defensive programming is to make your code fail quickly and visibly when something goes wrong, rather than silently producing incorrect results. Assertions help you achieve this by making your assumptions explicit and verifiable.

Errors and Assertions

Learn how we can ensure that our application is in a valid state using compile-time and run-time assertions.

Questions & Answers

Answers are generated by AI models and may not have been reviewed. Be mindful when running any code on your device.

Using Assert in Release Builds
The lesson mentions that assert() calls are sometimes stripped out in release builds for performance. What if I want to keep some critical assertions enabled in release builds?
Using static_assert with Non-constexpr Expressions
Can static_assert() be used with expressions that are not known at compile-time, such as values read from a file or user input?
Avoiding Side Effects in Assertions
Is it okay to use assert() with expressions that have side effects, like assert(++x > 0)? Or should assertions be side-effect free?
Assertions vs Exceptions
When should I use assertions vs throwing exceptions? They seem to serve similar purposes.
Using static_assert in Template Code
The lesson shows an example of using static_assert() with std::is_floating_point to validate template parameters. What are some other common type traits I can use for template validation?
Or Ask your Own Question
Get an immediate answer to your specific question using our AI assistant