C++ developer tool for detecting deadlocks
CppGuard is know part of https://github.com/JochenBaier/BugInsight
CppGuard is developer tool for testing C++ applications made with Visual Studio for deadlocks and wrong lock usage. I can be used manually and within a CI system. CppGuard consists of the DLL cppguard.dll and the header cppguard.h.
CppGuard uses the deadlock detection algorithm from C++ library Abseil. This algorithm will detect a potential deadlock even if the executed program does not actually deadlock. It maintains an acquired-before graph and checks for cycles in this graph. The underlying graph algorithm is described here. There is no relationship between the Abseil project and CppGuard.
If locks are acquired in inconsistent order, it depends on the timing whether a deadlock occur or not. Example with 2 threads and mutex a and b:
std::mutex a;
std::mutex b;
//lock order: a -> b
std::thread t1([&]() {
const std::lock_guard<std::mutex> lock_a(a);
const std::lock_guard<std::mutex> lock_b(b);
});
//lock order: b -> a
std::thread t2([&]() {
const std::lock_guard<std::mutex> lock_b(b);
const std::lock_guard<std::mutex> lock_a(a);
});
t1.join();
t2.join();
If t2 will acquired lock b after t1 has locked a and b no deadlock occur. if t1 got lock a and t2 got lock b a deadlock occur.
CppGuard has detected the potential deadlock:
==========================================================================================================
CppGuard: [Error] Potential deadlock at lock: 0x1e2599ebd0, thread ID: 50092.
Lock Call Stack:
C:\dev\cppguard\cppguard\deadlock_monitor.cpp(152,0): deadlock_monitor_t::dlc_deadlock_check_before_lock
C:\dev\cppguard\cppguard\api_monitors\mutex_monitor.cpp(37,0): cppguard_mtx_lock
...
A cycle in the historical lock ordering graph has been observed:
Thread ID: 50092
Holding lock: 0x1e2599ec40
Wait for lock: 0x1e2599ebd0
Call Stack:
C:\dev\cppguard\cppguard\api_monitors\mutex_monitor.cpp(37,0): cppguard_mtx_lock
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\mutex(56,0): std::_Mutex_base::lock
...
Thread ID: 48624
Holding lock: 0x1e2599ebd0
Wait for lock: 0x1e2599ec40
Call Stack:
C:\dev\cppguard\cppguard\api_monitors\mutex_monitor.cpp(37,0): cppguard_mtx_lock
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\mutex(56,0): std::_Mutex_base::lock
...
Deadlock detection: A warning or an error is generated if potential deadlock (a cycle) is detected (from Abseil algorithm)
Detect wrong lock usage: Detect locks which are released by threads which do no hold them (from Abseil algorithm)
Lock watchdog: The time a lock is waiting for a lock or holding a lock is monitored and a log or error is created if a maximum time is exceeded
Runs on Windows OS with the native lock APIs of Windows: Critical Section, std::mutex and std::recursive_mutex
Test C/C++ DLLs loaded in a Java or a .Net programs
Overhead depends on usage. Pretty good for IO bound applications (e.g. TCPI/IP based)
Works with Debug, Release and RelWithDebInfo builds
For basic usage no source code changes are needed. Minor changes (minimum 2 lines) to the build system (CMake, or Visual Studio Project) are needed
see Quickstart
CppGuard provides:
InitializeCriticalSection(), EnterCriticalSection(), TryEnterCriticalSection(), LeaveCriticalSection(), DeleteCriticalSection()
std::mutex, std::recursive_mutex: via internal functions from mutex header_Mtx_*()
std::lock_guard, std::unique_lock
see Options
CppGuard is licensed under the terms of the Apache 2.0 license. See LICENSE for more information.