aboutsummaryrefslogtreecommitdiff
path: root/docs/DesignDocs/DebugMode.rst
blob: 3b997d44607011383cf73b28cf930038ee16be57 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
==========
Debug Mode
==========

.. contents::
   :local:

.. _using-debug-mode:

Using Debug Mode
================

Libc++ provides a debug mode that enables assertions meant to detect incorrect
usage of the standard library. By default these assertions are disabled but
they can be enabled using the ``_LIBCPP_DEBUG`` macro.

**_LIBCPP_DEBUG** Macro
-----------------------

**_LIBCPP_DEBUG**:
  This macro is used to enable assertions and iterator debugging checks within
  libc++. By default it is undefined.

  **Values**: ``0``, ``1``

  Defining ``_LIBCPP_DEBUG`` to ``0`` or greater enables most of libc++'s
  assertions. Defining ``_LIBCPP_DEBUG`` to ``1`` enables "iterator debugging"
  which provides additional assertions about the validity of iterators used by
  the program.

  Note that this option has no effect on libc++'s ABI

**_LIBCPP_DEBUG_USE_EXCEPTIONS**:
  When this macro is defined ``_LIBCPP_ASSERT`` failures throw
  ``__libcpp_debug_exception`` instead of aborting. Additionally this macro
  disables exception specifications on functions containing ``_LIBCPP_ASSERT``
  checks. This allows assertion failures to correctly throw through these
  functions.

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 two
different assertion handlers, the default handler
``std::__libcpp_abort_debug_handler`` which aborts the program, and
``std::__libcpp_throw_debug_handler`` which throws an instance of
``std::__libcpp_debug_exception``. Libc++ can be changed to use the throwing
assertion handler as follows:

.. code-block:: cpp

  #define _LIBCPP_DEBUG 1
  #include <string>
  int main() {
    std::__libcpp_debug_function = std::__libcpp_throw_debug_function;
    try {
      std::string::iterator bad_it;
      std::string str("hello world");
      str.insert(bad_it, '!'); // causes debug assertion
    } catch (std::__libcpp_debug_exception const&) {
      return EXIT_SUCCESS;
    }
    return EXIT_FAILURE;
  }

Debug Mode Checks
=================

Libc++'s debug mode offers two levels of checking. The first enables various
precondition checks throughout libc++. The second additionally enables
"iterator debugging" which checks the validity of iterators used by the program.

Basic Checks
============

These checks are enabled when ``_LIBCPP_DEBUG`` is defined to either 0 or 1.

The following checks are enabled by ``_LIBCPP_DEBUG``:

  * FIXME: Update this list

Iterator Debugging Checks
=========================

These checks are enabled when ``_LIBCPP_DEBUG`` is defined to 1.

The following containers and STL 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.