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.
Basic checks (_LIBCPP_DEBUG == 0
)¶
When _LIBCPP_DEBUG
is defined to 0
(to be understood as level 0
), some
debugging checks are enabled. The non-exhaustive list of things is:
Many algorithms, such as
binary_search
,merge
,next_permutation
, andsort
, 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_LIBCPP_DEBUG
, and causes the library to violate some of the Standard’s complexity clauses.FIXME: Update this list
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
}