About
Simple, portable, and self-contained stacktrace library for C++11 and newer
# Cpptrace
[-Community%20Discord-blue?labelColor=2C3239&color=7289DA&style=flat&logo=discord&logoColor=959DA5)](https://discord.gg/frjaAZvqUZ)
Cpptrace is a simple and portable C++ stacktrace library supporting C++11 and greater on Linux, macOS, and Windows
including MinGW and Cygwin environments. The goal: Make stack traces simple for once.
In addition to providing access to stack traces, cpptrace also provides a mechanism for getting stacktraces from thrown
exceptions which is immensely valuable for debugging and triaging. More info [below](#traces-from-all-exceptions-cpptrace_try-and-cpptrace_catch).
Cpptrace also has a C API, docs [here](docs/c-api.md).
## Table of Contents
- [30-Second Overview](#30-second-overview)
- [CMake FetchContent Usage](#cmake-fetchcontent-usage)
- [Prerequisites](#prerequisites)
- [Basic Usage](#basic-usage)
- [`namespace cpptrace`](#namespace-cpptrace)
- [Stack Traces](#stack-traces)
- [Object Traces](#object-traces)
- [Raw Traces](#raw-traces)
- [Utilities](#utilities)
- [Formatting](#formatting)
- [Transforms](#transforms)
- [Configuration](#configuration)
- [Logging](#logging)
- [Traces From All Exceptions (`CPPTRACE_TRY` and `CPPTRACE_CATCH`)](#traces-from-all-exceptions-cpptrace_try-and-cpptrace_catch)
- [Removing the `CPPTRACE_` prefix](#removing-the-cpptrace_-prefix)
- [How it works](#how-it-works)
- [Performance](#performance)
- [Rethrowing Exceptions](#rethrowing-exceptions)
- [`cpptrace::try_catch`](#cpptracetry_catch)
- [Traces from SEH exceptions](#traces-from-seh-exceptions)
- [Traced Exception Objects](#traced-exception-objects)
- [Wrapping std::exceptions](#wrapping-stdexceptions)
- [Exception handling with cpptrace exception objects](#exception-handling-with-cpptrace-exception-objects)
- [Terminate Handling](#terminate-handling)
- [Signal-Safe Tracing](#signal-safe-tracing)
- [Utility Types](#utility-types)
- [Headers](#headers)
- [Libdwarf Tuning](#libdwarf-tuning)
- [JIT Support](#jit-support)
- [Loading Libraries at Runtime](#loading-libraries-at-runtime)
- [ABI Versioning](#abi-versioning)
- [Supported Debug Formats](#supported-debug-formats)
- [How to Include The Library](#how-to-include-the-library)
- [CMake FetchContent](#cmake-fetchcontent)
- [System-Wide Installation](#system-wide-installation)
- [Local User Installation](#local-user-installation)
- [Use Without CMake](#use-without-cmake)
- [Installation Without Package Managers or FetchContent](#installation-without-package-managers-or-fetchcontent)
- [Package Managers](#package-managers)
- [Conan](#conan)
- [Vcpkg](#vcpkg)
- [C++20 Modules](#c20-modules)
- [Platform Logistics](#platform-logistics)
- [Windows](#windows)
- [macOS](#macos)
- [Library Back-Ends](#library-back-ends)
- [Summary of Library Configurations](#summary-of-library-configurations)
- [Testing Methodology](#testing-methodology)
- [Notes About the Library](#notes-about-the-library)
- [FAQ](#faq)
- [What about C++23 ``?](#what-about-c23-stacktrace)
- [What does cpptrace have over other C++ stacktrace libraries?](#what-does-cpptrace-have-over-other-c-stacktrace-libraries)
- [I'm getting undefined standard library symbols like `std::__1::basic_string` on MacOS](#im-getting-undefined-standard-library-symbols-like-std__1basic_string-on-macos)
- [Contributing](#contributing)
- [License](#license)
# 30-Second Overview
Generating stack traces is as easy as:
```cpp
#include
void trace() {
cpptrace::generate_trace().print();
}
```
Cpptrace can also retrieve function inlining information on optimized release builds:
Cpptrace provides access to resolved stack traces as well as fast and lightweight raw traces (just addresses) that can
be resolved later:
```cpp
const auto raw_trace = cpptrace::generate_raw_trace();
// then later
raw_trace.resolve().print();
```
One of the most important features cpptrace offers is the ability to retrieve stack traces on arbitrary exceptions.
More information on this system [below](#traces-from-all-exceptions-cpptrace_try-and-cpptrace_catch).
```cpp
#include
#include
#include
void foo() {
throw std::runtime_error("foo failed");
}
int main() {
CPPTRACE_TRY {
foo();
} CPPTRACE_CATCH(const std::exception& e) {
std::cerr<<"Exception: "<
void trace() {
throw cpptrace::logic_error("This wasn't supposed to happen!");
}
```
Additional notable features:
- Utilities for demangling
- Utilities for catching `std::exception`s and wrapping them in traced exceptions
- Signal-safe stack tracing
- As far as I can tell cpptrace is the only library which can truly do this in a signal-safe manner
- Source code snippets in traces
- Extensive configuration options for [trace formatting](#formatting) and pretty-printing
## CMake FetchContent Usage
```cmake
include(FetchContent)
FetchContent_Declare(
cpptrace
GIT_REPOSITORY https://github.com/jeremy-rifkin/cpptrace.git
GIT_TAG v1.0.4 #
)
FetchContent_MakeAvailable(cpptrace)
target_link_libraries(your_target cpptrace::cpptrace)
# Needed for shared library builds on windows: copy cpptrace.dll to the same directory as the
# executable for your_target
if(WIN32)
add_custom_command(
TARGET your_target POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$
$
)
endif()
```
Be sure to configure with `-DCMAKE_BUILD_TYPE=Debug` or `-DCMAKE_BUILD_TYPE=RelWithDebInfo` for symbols and line
information.
On macOS it is recommended to generate a `.dSYM` file, see [Platform Logistics](#platform-logistics) below.
For other ways to use the library, such as through package managers, a system-wide installation, or on a platform
without internet access see [How to Include The Library](#how-to-include-the-library) below.
# Prerequisites
> [!IMPORTANT]
> Debug info (`-g`/`/Z7`/`/Zi`/`/DEBUG`/`-DBUILD_TYPE=Debug`/`-DBUILD_TYPE=RelWithDebInfo`) is required for complete
> trace information.
# Basic Usage
`cpptrace::generate_trace()` can be used to generate a `stacktrace` object at the current call site. Resolved frames can
be accessed from this object with `.frames` and the trace can be printed with `.print()`. Cpptrace also provides a
method to get light-weight raw traces with `cpptrace::generate_raw_trace()`, which are just vectors of program counters,
which can be resolved at a later time.
# `namespace cpptrace`
All functions are thread-safe unless otherwise noted.
## Stack Traces
The core resolved stack trace object. Generate a trace with `cpptrace::generate_trace()` or
`cpptrace::stacktrace::current()`. On top of a set of helper functions `struct stacktrace` allows
direct access to frames as well as iterators.
`cpptrace::stacktrace::print` can be used to print a stacktrace. `cpptrace::stacktrace::print_with_snippets` can be used
to print a stack trace with source code snippets.
```
…
```
## Object Traces
Object traces contain the most basic information needed to construct a stack trace outside the currently running
executable. It contains the raw address, the address in the binary (ASLR and the object file's memory space and whatnot
is resolved), and the path to the object the instruction pointer is located in.
```
…
```
## Raw Traces
Raw trace access: A vector of program counters. These are ideal for fast and cheap traces you want to resolve later.
Note it is important executables and shared libraries in memory aren't somehow unmapped otherwise libdl calls (and
`GetModuleFileName` in windows) will fail to figure out where the program counter corresponds to.
```cpp
namespace cpptrace {
struct raw_trace {
std::vector frames;
static raw_trace current(std::size_t skip = 0);
static raw_trace current(std::size_t skip, std::size_t max_depth);
object_trace resolve_object_trace() const;
stacktrace resolve() const;
void clear();
bool empty() const noexcept;
/* iterators exist for this object */
};
raw_trace generate_raw_trace(std::size_t skip = 0);
raw_trace generate_raw_trace(std::size_t skip, std::size_t max_depth);
}
```
## Utilities
`cpptrace::demangle` is a helper function for name demangling, since it has to implement that helper internally anyways.
`cpptrace::basename` is a helper for custom formatters that extracts a base file name from a path.
`cpptrace::prettify_symbol` is a helper for custom formatters that applies a number of transformations to clean up long
symbol names. For example, it turns `std::__cxx11::basic_string, std::allocator >`
into `std::string`.
`cpptrace::prune_symbol` is a helper for custom formatters that prunes demangled symbols by removing return types,
template arguments, and function parameters. It also does some minimal normalization. For example, it prunes
`ns::S::~S()` to `ns::S::~S`. If cpptrace is unable to parse the symbol it will return the original symbol.
`cpptrace::get_snippet` gets a text snippet, if possible, from for the given source file for +/- `context_size` lines
around `line`.
`cpptrace::isatty` and the fileno definitions are useful for deciding whether to use color when printing stack traces.
`cpptrace::register_terminate_handler()` is a helper function to set a custom `std::terminate` handler that prints a
stack trace from a cpptrace exception (more info below) and otherwise behaves like the normal terminate handler.
```
…
```
## Formatting
Cpptrace provides a configurable formatter for stack trace printing which supports some common options. Formatters are
configured with a sort of builder pattern, e.g.:
```cpp
auto formatter = cpptrace::formatter{}
.header("Stack trace:")
.addresses(cpptrace::formatter::address_mode::object)
.snippets(true);
```
This API is available through the `` header.
Synopsis:
```
…
```
Options:
| Setting | Description | Default |
| ----------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------ |
| `header` | Header line printed before the trace | `Stack trace (most recent call first):` |
| `colors` | Default color mode for the trace | `automatic`, which attempts to detect if the target stream is a terminal |
| `addresses` | Raw addresses, object addresses, or no addresses | `raw` |
| `paths` | Full paths or just filenames | `full` |
| `snippets` | Whether to include source code snippets | `false` |
| `snippet_context` | How many lines of source context to show in a snippet | `2` |
| `columns` | Whether to include column numbers if present | `true`