| @node Stack traces | |
| @section Stack traces | |
| @c Copyright (C) 2024--2026 Free Software Foundation, Inc. | |
| @c Permission is granted to copy, distribute and/or modify this document | |
| @c under the terms of the GNU Free Documentation License, Version 1.3 or | |
| @c any later version published by the Free Software Foundation; with no | |
| @c Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A | |
| @c copy of the license is at <https://www.gnu.org/licenses/fdl-1.3.en.html>. | |
| @c Written by Bruno Haible. | |
| @mindex stack-trace | |
| Printing a stack trace | |
| was traditionally seen as a feature of the debugging environment | |
| and thus only implemented in the debuggers (@command{gdb} etc.). | |
| However, they are also useful in production code, | |
| for use in two circumstances: | |
| @itemize | |
| @item | |
| When a problem occurs on a user's machine, | |
| when the user is merely a user, not a programmer. | |
| @item | |
| In unit tests that run in continuous-integration environments. | |
| In such environments, the virtual machine is discarded | |
| immediately after the tests have run. | |
| It is not possible to run a debugger in such environments. | |
| @end itemize | |
| @noindent | |
| And in fact, printing a stack trace is part of the basic runtime system | |
| in programming languages such as | |
| Java (@url{https://docs.oracle.com/javase/8/docs/api/java/lang/Throwable.html#printStackTrace--, printStackTrace method}), | |
| Python (@url{https://docs.python.org/3/library/traceback.html, print_exception method}), | |
| Go (@url{https://pkg.go.dev/runtime/debug#PrintStack, PrintStack function}), | |
| and | |
| ISO C++ 23 (@url{https://en.cppreference.com/w/cpp/utility/basic_stacktrace, std::stacktrace class}). | |
| Gnulib provides a module @samp{stack-trace} with this feature: | |
| @code{print_stack_trace ()} | |
| prints a stack trace of the current thread to standard error. | |
| For it to work best, three requirements need to be met: | |
| @itemize | |
| @item | |
| The @url{https://github.com/ianlancetaylor/libbacktrace, libbacktrace library} | |
| or GCC's sanitizer library @code{libasan} needs to be installed. | |
| @item | |
| The program needs to be compiled with debugging information (option @code{-g}). | |
| @item | |
| On macOS, where debugging information | |
| is stored in a separate directory rather than in the compiled binary | |
| (see @url{https://stackoverflow.com/questions/10044697/#12827463}), | |
| the @code{dsymutil} program needs to be used when linking, | |
| and the debugging information needs to be copied when the program is installed. | |
| Cf. @url{https://github.com/ianlancetaylor/libbacktrace/issues/122#issuecomment-2122589147}. | |
| @end itemize | |
| When these requirements are not met, the function @code{print_stack_trace ()} | |
| either prints a stack trace without source file names and line numbers, | |
| or prints nothing at all. | |
| @mindex abort-debug | |
| Gnulib also provides a module @samp{abort-debug}, | |
| that overrides the @code{abort} function so that | |
| it prints the stack trace of the current thread, before actually aborting. | |
| Thus, @code{abort ()} remains the idiom of choice | |
| for signaling a fatal situation that requires developer attention: | |
| it is useful both in debugging environments and production code. | |
| Note: | |
| While the original @code{abort} function is safe to call in signal handlers, | |
| the overridden @code{abort} function is not. | |
| In signal handlers, you will need to call the original @code{abort} function, | |
| by doing @code{#undef abort} first. |