Testing, Debugging & Sanitizers
টেস্টিং, ডিবাগিং ও sanitizer
1. Unit Testing with GoogleTest
test_math.cpp
#include <gtest/gtest.h>
#include "math.hpp"
TEST(MathTest, AddBasic) {
EXPECT_EQ(add(2, 3), 5);
}
TEST(MathTest, SquareNegative) {
EXPECT_EQ(square(-4), 16);
}
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
Alternatives: Catch2 (header-only, expressive), doctest (fastest compile).
2. Sanitizers — Cheap and Powerful
| Sanitizer | Flag | Catches |
|---|---|---|
| Address (ASan) | -fsanitize=address | Heap/stack overflow, use-after-free, leaks |
| Undefined Behavior (UBSan) | -fsanitize=undefined | Signed overflow, null deref, oob shifts |
| Thread (TSan) | -fsanitize=thread | Data races |
| Memory (MSan) | -fsanitize=memory | Uninitialized reads (Clang only) |
Recommended dev flag set
-g -O1 -fsanitize=address,undefined -fno-omit-frame-pointer
3. gdb Quick Reference
gdb session
g++ -g -O0 app.cpp -o app
gdb ./app
(gdb) # Common commands
break main # breakpoint at main
break file.cpp:42 # breakpoint at line
run # start program
next / n # next line (skip into calls)
step / s # step into call
print x / p x # print variable
backtrace / bt # show call stack
continue / c # resume
quit / q
4. assert & static_assert
assert.cpp
#include <cassert>
int divide(int a, int b) {
assert(b != 0); // runtime check (debug only)
return a / b;
}
static_assert(sizeof(int) == 4, "int must be 32-bit"); // compile-time
5. Profiling
- perf (Linux): sampling profiler,
perf record / perf report - callgrind (Valgrind): instruction-level call graph
- gperftools: heap and CPU profiler
- VTune (Intel): microarchitectural insights
6. Practice Problems
- Write a GoogleTest case for
square(int).✨ Show Answer
See section 1.
- Compile flags to find a use-after-free?
✨ Show Answer
g++ -fsanitize=address -g - Compile flag for signed overflow detection?
✨ Show Answer
g++ -fsanitize=undefined - Set a breakpoint at line 42 of main.cpp in gdb.
✨ Show Answer
break main.cpp:42 - Why is
static_assertbetter thanassertwhen possible?✨ Show Answer
Compile-time check — never runs at runtime, never costs anything, fails the build instead of the program.
- Why disable
assertin release?✨ Show Answer
Defining
NDEBUGturns assert into a no-op. Saves runtime cost. But: don't put side effects in assert! - A test with EXPECT_NEAR for floating-point.
✨ Show Answer
EXPECT_NEAR(computePi(), 3.14159, 1e-4); - Find a data race with TSan — flag?
✨ Show Answer
g++ -fsanitize=thread - Get a stack trace in gdb after a crash.
✨ Show Answer
(gdb) bt - Why must tests be reproducible?
✨ Show Answer
Flaky tests destroy trust. Use seeded RNGs, avoid timing-dependent assertions, mock external services.
Summary
Use a unit-testing framework (GoogleTest, Catch2). Compile dev builds with sanitizers —
ASan + UBSan are nearly free and catch real bugs. Use gdb when symbols matter.
static_assert for compile-time invariants. Profile with perf when performance matters.