Debug Mode¶
Using the debug mode¶
Libc++ provides a debug mode that enables special debugging checks meant to detect
incorrect usage of the standard library. These checks are disabled by default, but
they can be enabled using the _LIBCPP_DEBUG
macro.
Note that using the debug mode discussed in this document requires that the library
has been compiled with support for the debug mode (see LIBCXX_ENABLE_DEBUG_MODE_SUPPORT
).
Also note that while the debug mode has no effect on libc++’s ABI, it does have broad ODR implications. Users should compile their whole program at the same debugging level.
The various levels of checking provided by the debug mode follow.
No debugging checks (_LIBCPP_DEBUG
not defined)¶
When _LIBCPP_DEBUG
is not defined, there are no debugging checks performed by
the library. This is the default.
Comparator consistency checks (_LIBCPP_DEBUG == 1
)¶
Libc++ provides some checks for the consistency of comparators passed to algorithms. Specifically,
many algorithms such as binary_search
, merge
, next_permutation
, and sort
, wrap the
user-provided comparator to assert that !comp(y, x) whenever comp(x, y). This can cause the
user-provided comparator to be evaluated up to twice as many times as it would be without the
debug mode, and causes the library to violate some of the Standard’s complexity clauses.
Iterator debugging checks (_LIBCPP_DEBUG == 1
)¶
Defining _LIBCPP_DEBUG
to 1
enables “iterator debugging”, which provides
additional assertions about the validity of iterators used by the program.
The following containers and classes support iterator debugging:
std::string
std::vector<T>
(T != bool
)std::list
std::unordered_map
std::unordered_multimap
std::unordered_set
std::unordered_multiset
The remaining containers do not currently support iterator debugging. Patches welcome.
Randomizing Unspecified Behavior (_LIBCPP_DEBUG == 1
)¶
This also enables the randomization of unspecified behavior, for
example, for equal elements in std::sort
or randomizing both parts of
the partition after std::nth_element
call. This effort helps you to migrate
to potential future faster versions of these algorithms and deflake your tests
which depend on such behavior. To fix the seed, use
_LIBCPP_DEBUG_RANDOMIZE_UNSPECIFIED_STABILITY_SEED=seed
definition.
Handling Assertion Failures¶
When a debug assertion fails the assertion handler is called via the
std::__libcpp_debug_function
function pointer. It is possible to override
this function pointer using a different handler function. Libc++ provides a
the default handler, std::__libcpp_abort_debug_handler
, which aborts the
program. The handler may not return. Libc++ can be changed to use a custom
assertion handler as follows.
#define _LIBCPP_DEBUG 1
#include <string>
void my_handler(std::__libcpp_debug_info const&);
int main(int, char**) {
std::__libcpp_debug_function = &my_handler;
std::string::iterator bad_it;
std::string str("hello world");
str.insert(bad_it, '!'); // causes debug assertion
// control flow doesn't return
}