Outline
Purpose
Provide an object for streaming the current stack trace.
Classes
- See also
- balst_stacktraceprintutil
Description
This component provides a mechanism, balst::StackTracePrinter
, that when streamed (using a streaming operator) renders a description of the current call-stack to the supplied stream. This class can, at construction, be passed up to 3 optional arguments to drive the details with which the stack trace is to be performed. Not all properties of a stack trace are printed on all platforms because the set of properties describing a stack trace that are obtainable varies according to both the platform and build parameters. For example, on Solaris, source file names and line numbers are not provided. Function names and addresses are provided on all platforms. Streaming a balst::StackTracePrinter
always prints a description of the stack of the calling thread.
Usage
In this section we show the intended usage of this component.
Example 1: Streaming to BALL
First, we define a recursive function recurseAndPrintStack
that recurses 4 times, then calls << StackTracePrinter()
to obtain a stack trace and print it to BALL_LOG_FATAL
:
void recurseAndStreamStackDefault()
{
static int recurseCount = 0;
if (recurseCount++ < 4) {
recurseAndStreamStackDefault();
}
else {
}
}
Definition balst_stacktraceprinter.h:228
#define BALL_LOG_FATAL
Definition ball_log.h:1241
#define BALL_LOG_SET_NAMESPACE_CATEGORY(CATEGORY)
Definition ball_log.h:1137
which, on Linux, produces the output:
02SEP2021_21:55:58.619290 21325 140602555295616 FATAL /bb/.../balst_stacktr
aceprinter.t.cpp 733 UNINITIALIZED_LOGGER_MANAGER
(0): recurseAndStreamStackDefault()+0xcf at 0x408acc source:balst_stacktrac
eprinter.t.cpp:733 in balst_stacktraceprinter.t
(1): recurseAndStreamStackDefault()+0x2a at 0x408a27 source:balst_stacktrac
eprinter.t.cpp:735 in balst_stacktraceprinter.t
(2): recurseAndStreamStackDefault()+0x2a at 0x408a27 source:balst_stacktrac
eprinter.t.cpp:735 in balst_stacktraceprinter.t
(3): recurseAndStreamStackDefault()+0x2a at 0x408a27 source:balst_stacktrac
eprinter.t.cpp:735 in balst_stacktraceprinter.t
(4): recurseAndStreamStackDefault()+0x2a at 0x408a27 source:balst_stacktrac
eprinter.t.cpp:735 in balst_stacktraceprinter.t
(5): main+0x1a7 at 0x408ff8 source:balst_stacktraceprinter.t.cpp:901 in bal
st_stacktraceprinter.t
(6): __libc_start_main+0xf5 at 0x7fe0943de495 in /lib64/libc.so.6
(7): --unknown-- at 0x4074c5 in balst_stacktraceprinter.t
Note that long lines of output here have been hand-wrapped to fit into comments in this 79-column source file. Also note that if the full path of the executable or library is too long, only the basename will be displayed by the facility, while if it is short, then the full path will be displayed.
Then we define a similar recursive function, except that when we construct the StackTracePrinter
object, we pass 2 to the maxFrames
argument, indicating, for some reason, that we want to see only the top two stack frames:
void recurseAndStreamStackMaxFrames2()
{
static int recurseCount = 0;
if (recurseCount++ < 4) {
recurseAndStreamStackMaxFrames2();
}
else {
}
}
which produces the output:
02SEP2021_21:55:58.624623 21325 140602555295616 FATAL /bb/.../balst_stacktr
aceprinter.t.cpp 773 UNINITIALIZED_LOGGER_MANAGER
(0): recurseAndStreamStackMaxFrames2()+0xcf at 0x408be1 source:balst_stackt
raceprinter.t.cpp:773 in balst_stacktraceprinter.t
(1): recurseAndStreamStackMaxFrames2()+0x2a at 0x408b3c source:balst_stackt
raceprinter.t.cpp:775 in balst_stacktraceprinter.t
Now, we define another similar recursive function, except that when we construct the StackTracePrinter
object, we default maxFrames
to a large value by passing it -1, and turn off demangling by passing false
to the damanglingPreferredFlag
argument:
void recurseAndStreamStackNoDemangle()
{
static int recurseCount = 0;
if (recurseCount++ < 4) {
recurseAndStreamStackNoDemangle();
}
else {
}
}
which produces the output:
02SEP2021_21:55:58.636414 21325 140602555295616 FATAL /bb/.../balst_stacktr
aceprinter.t.cpp 798 UNINITIALIZED_LOGGER_MANAGER
(0): _Z31recurseAndStreamStackNoDemanglev+0xcf at 0x408cf6 source:balst_sta
cktraceprinter.t.cpp:798 in balst_stacktraceprinter.t
(1): _Z31recurseAndStreamStackNoDemanglev+0x2a at 0x408c51 source:balst_sta
cktraceprinter.t.cpp:800 in balst_stacktraceprinter.t
(2): _Z31recurseAndStreamStackNoDemanglev+0x2a at 0x408c51 source:balst_sta
cktraceprinter.t.cpp:800 in balst_stacktraceprinter.t
(3): _Z31recurseAndStreamStackNoDemanglev+0x2a at 0x408c51 source:balst_sta
cktraceprinter.t.cpp:800 in balst_stacktraceprinter.t
(4): _Z31recurseAndStreamStackNoDemanglev+0x2a at 0x408c51 source:balst_sta
cktraceprinter.t.cpp:800 in balst_stacktraceprinter.t
(5): main+0x1b1 at 0x409002 source:balst_stacktraceprinter.t.cpp:903 in bal
st_stacktraceprinter.t
(6): __libc_start_main+0xf5 at 0x7fe0943de495 in /lib64/libc.so.6
(7): --unknown-- at 0x4074c5 in balst_stacktraceprinter.t
Finally, we define another similar recursive function, except that we pass default values to the first 2 arguments of the StackTracePrinter
and pass 5 to the third additionalIgnoreFrames
argument. This indicates a number of frames from the top of the stack to be ignored, which may be desired if the caller wants to do the streaming from within their own stack trace facility, in which case the top couple of frames would be within that stack trace facility, and unwanted and distracting for clients of that facility:
void recurseAndStreamStackAddIgnore5()
{
static int recurseCount = 0;
if (recurseCount++ < 4) {
recurseAndStreamStackAddIgnore5();
}
else {
}
}
which produces the output:
02SEP2021_21:55:58.647501 21325 140602555295616 FATAL /bb/.../balst_stacktr
aceprinter.t.cpp 836 UNINITIALIZED_LOGGER_MANAGER
(0): main+0x1b6 at 0x409007 source:balst_stacktraceprinter.t.cpp:904 in bal
st_stacktraceprinter.t
(1): __libc_start_main+0xf5 at 0x7fe0943de495 in /lib64/libc.so.6
(2): --unknown-- at 0x4074c5 in balst_stacktraceprinter.t