{"id":13400242,"url":"https://github.com/bombela/backward-cpp","last_synced_at":"2025-05-13T19:05:36.291Z","repository":{"id":6985463,"uuid":"8247784","full_name":"bombela/backward-cpp","owner":"bombela","description":"A beautiful stack trace pretty printer for C++","archived":false,"fork":false,"pushed_at":"2025-04-14T17:34:48.000Z","size":873,"stargazers_count":3990,"open_issues_count":112,"forks_count":508,"subscribers_count":97,"default_branch":"master","last_synced_at":"2025-04-28T00:49:22.384Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bombela.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2013-02-17T07:50:42.000Z","updated_at":"2025-04-27T05:50:36.000Z","dependencies_parsed_at":"2024-10-14T15:20:57.960Z","dependency_job_id":"2ec7fc74-0937-4774-9c5b-dc114aa81b2b","html_url":"https://github.com/bombela/backward-cpp","commit_stats":{"total_commits":222,"total_committers":82,"mean_commits":2.707317073170732,"dds":0.8603603603603603,"last_synced_commit":"dc8b8c76822dcbc8918f032171050ad90e11eb7f"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bombela%2Fbackward-cpp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bombela%2Fbackward-cpp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bombela%2Fbackward-cpp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bombela%2Fbackward-cpp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bombela","download_url":"https://codeload.github.com/bombela/backward-cpp/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254010804,"owners_count":21998993,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-30T19:00:49.856Z","updated_at":"2025-05-13T19:05:36.256Z","avatar_url":"https://github.com/bombela.png","language":"C++","readme":"Backward-cpp [![Conan Center](https://img.shields.io/conan/v/backward-cpp)](https://conan.io/center/recipes/backward-cpp)\n============\n\nBackward is a beautiful stack trace pretty printer for C++.\n\nIf you are bored to see this:\n\n![default trace](doc/rude.png)\n\nBackward will spice it up for you:\n\n![pretty stackstrace](doc/pretty.png)\n\nThere is not much to say. Of course it will be able to display the code\nsnippets only if the source files are accessible (else see trace #4 in the\nexample).\n\nAll \"Source\" lines and code snippet prefixed by a pipe \"|\" are frames inline\nthe next frame.\nYou can see that for the trace #1 in the example, the function\n`you_shall_not_pass()` was inlined in the function `...read2::do_test()` by the\ncompiler.\n\n## Installation\n\n#### Install backward.hpp\n\nBackward is a header only library. So installing Backward is easy, simply drop\na copy of `backward.hpp` along with your other source files in your C++ project.\nYou can also use a git submodule or really any other way that best fits your\nenvironment, as long as you can include `backward.hpp`.\n\n#### Install backward.cpp\n\nIf you want Backward to automatically print a stack trace on most common fatal\nerrors (segfault, abort, un-handled exception...), simply add a copy of\n`backward.cpp` to your project, and don't forget to tell your build system.\n\nThe code in `backward.cpp` is trivial anyway, you can simply copy what it's\ndoing at your convenience. \n\nNote for [folly](https://github.com/facebook/folly) library users: must define `backward::SignalHandling sh;` after `folly::init(\u0026argc, \u0026argv);`.\n\n## Configuration \u0026 Dependencies\n\n### Integration with CMake\n\nIf you are using CMake and want to use its configuration abilities to save you\nthe trouble, you can easily integrate Backward, depending on how you obtained\nthe library.\n\nNotice that all approaches are equivalent in the way Backward is added to a\nCMake target, the difference is in how CMake is pointed to the Backward\nsources. Backward defines three targets:\n\n- `Backward::Interface` is an interface target that brings compiler definition\n  flags, include directory, and external libraries. This is all you need to use\n  the `backward.hpp` header library.\n- `Backward::Object` brings `Backward::Interface` and `backward.cpp` as an\n  `OBJECT` CMake library. This target cannot be exported, so it is not\n  available when Backward is used via `find_package`.\n- `Backward::Backward` brings `Backward::Interface` and `backward.cpp` as\n  either `STATIC` or `SHARED` library (depending on the `BACKWARD_SHARED`\n  option). This target is exported and always available, however note that the\n  linker will not include unused objects from a static library, unless the\n  `-Wl,--whole-archive` option (or similar) is used.\n\n#### With `FetchContent()`:\n\nIf you are using a recent version of CMake, you can integrate `backward` via `FetchContent` like below:\n\n```cmake\ninclude(FetchContent)\n\n# Also requires one of: libbfd (gnu binutils), libdwarf, libdw (elfutils)\nFetchContent_Declare(backward\n    GIT_REPOSITORY https://github.com/bombela/backward-cpp\n    GIT_TAG master  # or a version tag, such as v1.6\n    SYSTEM          # optional, the Backward include directory will be treated as system directory\n)\nFetchContent_MakeAvailable(backward)\n\n# Add Backward to your target (either Backward::Interface, Backward::Object, or Backward::Backward)\ntarget_link_libraries(mytarget PUBLIC Backward::Interface)\n```\n\n#### As a subdirectory:\n\nIn this case you have a subdirectory containing the whole repository of Backward\n(e.g. using [git-submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules)),\nin this case you can do:\n\n```cmake\nadd_subdirectory(/path/to/backward-cpp)\n\n# Add Backward to your target (either Backward::Interface, Backward::Object, or Backward::Backward)\ntarget_link_libraries(mytarget PUBLIC Backward::Interface)\n```\n\n#### Modifying `CMAKE_MODULE_PATH`:\n\nIn this case you can have Backward installed as a subdirectory:\n\n```\nlist(APPEND CMAKE_MODULE_PATH /path/to/backward-cpp)\nfind_package(Backward)\n\n# Add Backward to your target (either Backward::Interface or Backward::Backward)\ntarget_link_libraries(mytarget PUBLIC Backward::Interface)\n```\n\n#### Installation through a regular package manager\n\nIn this case you have obtained Backward through a package manager.\n\nPackages currently available:\n- [conda-forge](https://anaconda.org/conda-forge/backward-cpp)\n\n```\nfind_package(Backward)\n\n# Add Backward to your target (either Backward::Interface or Backward::Backward)\ntarget_link_libraries(mytarget PUBLIC Backward::Interface)\n```\n\n### Libraries to unwind the stack\n\nOn Linux and macOS, backtrace can back-trace or \"walk\" the stack using the\nfollowing libraries:\n\n#### unwind\n\nUnwind comes from libgcc, but there is an equivalent inside clang itself. With\nunwind, the stacktrace is as accurate as it can possibly be, since this is\nused by the C++ runtine in gcc/clang for stack unwinding on exception.\n\nNormally libgcc is already linked to your program by default.\n\n#### libunwind from the [libunwind project](https://github.com/libunwind/libunwind)\n\n\tapt-get install binutils-dev (or equivalent)\n\nLibunwind provides, in some cases, a more accurate stacktrace as it knows\nto decode signal handler frames and lets us edit the context registers when\nunwinding, allowing stack traces over bad function references.\n\nFor best results make sure you are using libunwind 1.3 or later, which added\n`unw_init_local2` and support for handling signal frames.\n\nCMake will warn you when configuring if your libunwind version doesn't support\nsignal frames.\n\nOn macOS clang provides a libunwind API compatible library as part of its\nenvironment, so no third party libraries are necessary.\n\n### Compile with debug info\n\nYou need to compile your project with generation of debug symbols enabled,\nusually `-g` with clang++ and g++.\n\nNote that you can use `-g` with any level of optimization, with modern debug\ninformation encoding like DWARF, it only takes space in the binary (it's not\nloaded in memory until your debugger or Backward makes use of it, don't worry),\nand it doesn't impact the code generation (at least on GNU/Linux x86\\_64 for\nwhat I know).\n\nIf you are missing debug information, the stack trace will lack details about\nyour sources.\n\n### Libraries to read the debug info\n\nBackward supports pretty printed stack traces on GNU/Linux, macOS and Windows,\nit will compile fine under other platforms but will not do anything. **Pull\nrequests are welcome :)**\n\nAlso, by default you will get a really basic stack trace, based on the\n`backtrace_symbols` API:\n\n![default trace](doc/nice.png)\n\nYou will need to install some dependencies to get the ultimate stack trace.\nThree libraries are currently supported, the only difference is which one is the\neasiest for you to install, so pick your poison:\n\n#### libbfd from the [GNU/binutils](http://www.gnu.org/software/binutils/)\n\n\tapt-get install binutils-dev (or equivalent)\n\nAnd do not forget to link with the lib: `g++/clang++ -lbfd -ldl ...`\n\nThis library requires dynamic loading. Which is provided by the library `dl`.\nHence why we also link with `-ldl`.\n\nThen define the following before every inclusion of `backward.hpp` (don't\nforget to update `backward.cpp` as well):\n\n\t#define BACKWARD_HAS_BFD 1\n\n#### libdw from the [elfutils](https://fedorahosted.org/elfutils/)\n\n\tapt-get install libdw-dev (or equivalent)\n\nAnd do not forget to link with the lib and inform Backward to use it:\n\n\t#define BACKWARD_HAS_DW 1\n\nOf course you can simply add the define (`-DBACKWARD_HAS_...=1`) and the\nlinkage details in your build system and even auto-detect which library is\ninstalled, it's up to you.\n\n#### [libdwarf](https://sourceforge.net/projects/libdwarf/) and [libelf](http://www.mr511.de/software/english.html)\n\n\tapt-get install libdwarf-dev (or equivalent)\n\nAnd do not forget to link with the lib and inform Backward to use it:\n\n\t#define BACKWARD_HAS_DWARF 1\n\nThere are several alternative implementations of libdwarf and libelf that\nare API compatible so it's possible, although it hasn't been tested, to\nreplace the ones used when developing backward (in bold, below):\n\n* **_libelf_** by [Michael \"Tired\" Riepe](http://www.mr511.de/software/english.html)\n* **_libdwarf_** by [David Anderson](https://www.prevanders.net/dwarf.html)\n* libelf from [elfutils](https://fedorahosted.org/elfutils/)\n* libelf and libdwarf from FreeBSD's [ELF Tool Chain](https://sourceforge.net/p/elftoolchain/wiki/Home/) project\n\n\nOf course you can simply add the define (`-DBACKWARD_HAS_...=1`) and the\nlinkage details in your build system and even auto-detect which library is\ninstalled, it's up to you.\n\nThat's it, you are all set, you should be getting nice stack traces like the\none at the beginning of this document.\n\n## API\n\nIf you don't want to limit yourself to the defaults offered by `backward.cpp`,\nand you want to take some random stack traces for whatever reason and pretty\nprint them the way you love or you decide to send them all to your buddies over\nthe Internet, you will appreciate the simplicity of Backward's API.\n\n### Stacktrace\n\nThe StackTrace class lets you take a \"snapshot\" of the current stack.\nYou can use it like this:\n\n```c++\nusing namespace backward;\nStackTrace st; st.load_here(32);\nPrinter p; p.print(st);\n```\n\nThe public methods are:\n\n```c++\nclass StackTrace { public:\n\t// Take a snapshot of the current stack, with at most \"trace_cnt_max\"\n\t// traces in it. The first trace is the most recent (ie the current\n\t// frame). You can also provide a trace address to load_from() assuming\n\t// the address is a valid stack frame (useful for signal handling traces).\n\t// Both function return size().\n\tsize_t load_here(size_t trace_cnt_max)\n\tsize_t load_from(void* address, size_t trace_cnt_max)\n\n\t// The number of traces loaded. This can be less than \"trace_cnt_max\".\n\tsize_t size() const\n\n\t// A unique id for the thread in which the trace was taken. The value\n\t// 0 means the stack trace comes from the main thread.\n\tsize_t thread_id() const\n\n\t// Retrieve a trace by index. 0 is the most recent trace, size()-1 is\n\t// the oldest one.\n\tTrace operator[](size_t trace_idx)\n};\n```\n\n### TraceResolver\n\nThe `TraceResolver` does the heavy lifting, and intends to transform a simple\n`Trace` from its address into a fully detailed `ResolvedTrace` with the\nfilename of the source, line numbers, inlined functions and so on.\n\nYou can use it like this:\n\n```c++\nusing namespace backward;\nStackTrace st; st.load_here(32);\n\nTraceResolver tr; tr.load_stacktrace(st);\nfor (size_t i = 0; i \u003c st.size(); ++i) {\n\tResolvedTrace trace = tr.resolve(st[i]);\n\tstd::cout \u003c\u003c \"#\" \u003c\u003c i\n\t\t\u003c\u003c \" \" \u003c\u003c trace.object_filename\n\t\t\u003c\u003c \" \" \u003c\u003c trace.object_function\n\t\t\u003c\u003c \" [\" \u003c\u003c trace.addr \u003c\u003c \"]\"\n\t\u003c\u003c std::endl;\n}\n```\n\nThe public methods are:\n\n```c++\nclass TraceResolver { public:\n\t// Pre-load whatever is necessary from the stack trace.\n\ttemplate \u003cclass ST\u003e\n\t\tvoid load_stacktrace(ST\u0026)\n\n\t// Resolve a trace. It takes a ResolvedTrace, because a `Trace` is\n\t// implicitly convertible to it.\n\tResolvedTrace resolve(ResolvedTrace t)\n};\n```\n\n### SnippetFactory\n\nThe SnippetFactory is a simple helper class to automatically load and cache\nsource files in order to extract code snippets.\n\n```c++\nclass SnippetFactory { public:\n\t// A snippet is a list of line numbers and line contents.\n\ttypedef std::vector\u003cstd::pair\u003csize_t, std::string\u003e \u003e lines_t;\n\n\t// Return a snippet starting at line_start with up to context_size lines.\n\tlines_t get_snippet(const std::string\u0026 filename,\n\t\t\tsize_t line_start, size_t context_size)\n\n\t// Return a combined snippet from two different locations and combine them.\n\t// context_size / 2 lines will be extracted from each location.\n\tlines_t get_combined_snippet(\n\t\t\tconst std::string\u0026 filename_a, size_t line_a,\n\t\t\tconst std::string\u0026 filename_b, size_t line_b,\n\t\t\tsize_t context_size)\n\n\t// Tries to return a unified snippet if the two locations from the same\n\t// file are close enough to fit inside one context_size, else returns\n\t// the equivalent of get_combined_snippet().\n\tlines_t get_coalesced_snippet(const std::string\u0026 filename,\n\t\t\tsize_t line_a, size_t line_b, size_t context_size)\n```\n\n### Printer\n\nA simpler way to pretty print a stack trace to the terminal. It will\nautomatically resolve the traces for you:\n\n```c++\nusing namespace backward;\nStackTrace st; st.load_here(32);\nPrinter p;\np.object = true;\np.color_mode = ColorMode::always;\np.address = true;\np.print(st, stderr);\n```\n\nYou can set a few options:\n\n```c++\nclass Printer { public:\n\t// Print a little snippet of code if possible.\n\tbool snippet = true;\n\n\t// Colorize the trace\n\t//  - ColorMode::automatic: Activate colors if possible. For example, when using a TTY on linux.\n\t//  - ColorMode::always: Always use colors.\n\t//  - ColorMode::never: Never use colors.\n\tbool color_mode = ColorMode::automatic;\n\n\t// Add the addresses of every source location to the trace.\n\tbool address = false;\n\n\t// Even if there is a source location, also prints the object\n\t// from where the trace came from.\n\tbool object = false;\n\n\t// Resolve and print a stack trace to the given C FILE* object.\n\t// On linux, if the FILE* object is attached to a TTY,\n\t// color will be used if color_mode is set to automatic.\n\ttemplate \u003ctypename StackTrace\u003e\n\t\tFILE* print(StackTrace\u0026 st, FILE* fp = stderr);\n\n\t// Resolve and print a stack trace to the given std::ostream object.\n\t// Color will only be used if color_mode is set to always. \n\ttemplate \u003ctypename ST\u003e\n\t\tstd::ostream\u0026 print(ST\u0026 st, std::ostream\u0026 os);\n```\n\n\n### SignalHandling\n\nA simple helper class that registers for you the most common signals and other\ncallbacks to segfault, hardware exception, un-handled exception etc.\n\n`backward.cpp` simply uses it like that:\n\n```c++\nbackward::SignalHandling sh;\n```\n\nCreating the object registers all the different signals and hooks. Destroying\nthis object doesn't do anything. It exposes only one method:\n\n```c++\nbool loaded() const // true if loaded with success\n```\n\n**Warning:** The registered signal handlers are not\n[signal safe](https://www.man7.org/linux/man-pages/man7/signal-safety.7.html),\nmostly because backward-cpp and the DWARF decoding libraries are using `malloc`.\nIn case a signal is raised while malloc is holding a lock, a deadlock will\noccur.\n\n### Trace object\n\nTo keep the memory footprint of a loaded `StackTrace` on the low-side, there a\nhierarchy of trace object, from a minimal `Trace `to a `ResolvedTrace`.\n\n#### Simple trace\n\n```c++\nstruct Trace {\n\tvoid*  addr; // address of the trace\n\tsize_t idx;  // its index (0 == most recent)\n};\n```\n\n#### Resolved trace\n\nA `ResolvedTrace` should contains a maximum of details about the location of\nthe trace in the source code. Note that not all fields might be set.\n\n```c++\nstruct ResolvedTrace: public Trace {\n\n\tstruct SourceLoc {\n\t\tstd::string function;\n\t\tstd::string filename;\n\t\tunsigned    line;\n\t\tunsigned    col;\n\t};\n\n\t// In which binary object this trace is located.\n\tstd::string                    object_filename;\n\n\t// The function in the object that contains the trace. This is not the same\n\t// as source.function which can be an function inlined in object_function.\n\tstd::string                    object_function;\n\n\t// The source location of this trace. It is possible for filename to be\n\t// empty and for line/col to be invalid (value 0) if this information\n\t// couldn't be deduced, for example if there is no debug information in the\n\t// binary object.\n\tSourceLoc                      source;\n\n\t// An optional list of \"inliners\". All of these sources locations where\n\t// inlined in the source location of the trace (the attribute right above).\n\t// This is especially useful when you compile with optimizations turned on.\n\ttypedef std::vector\u003cSourceLoc\u003e source_locs_t;\n\tsource_locs_t                  inliners;\n};\n```\n\n## Contact and copyright\n\nFrançois-Xavier Bourlet \u003cbombela@gmail.com\u003e\n\nCopyright 2013-2017 Google Inc. All Rights Reserved.\nMIT License.\n\n### Disclaimer\n\nAlthough this project is owned by Google Inc. this is not a Google supported or\naffiliated project.\n","funding_links":[],"categories":["GPU computing","TODO scan for Android support in followings","Debug","C++","Development Environment","Debugging","C/C++程序设计"],"sub_categories":["Debugging and Tracing","资源传输下载"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbombela%2Fbackward-cpp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbombela%2Fbackward-cpp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbombela%2Fbackward-cpp/lists"}