BDE 4.14.0 Production release
|
Provide low-level utilities for obtaining & printing a stack-trace.
balst::StackTrace
objectsThis component provides a namespace for functions used in obtaining and printing a stack-trace. Note that clients interested in simply printing a stack-trace are encouraged to use the balst_stacktraceprintutil component instead.
This section illustrates intended usage for this component.
The following examples demonstrate two distinct ways to load and print a stack-trace with balst::StackTraceUtil
using (1) loadStackTraceFromStack
and (2) loadStackTraceFromAddresses
.
We start by defining a routine, recurseExample1
, that will recurse the specified depth
times, then call traceExample1
:
Then, we define the function traceExample1
, that will print a stack-trace:
Now, we create a balst::StackTrace
object and call loadStackTraceFrameStack
to load the information from the stack of the current thread into the stack-trace object.
In this call to loadStackTraceFromStack
, we use the default value of maxFrames
, which is at least 1024 and the default value for demanglingPreferredFlag
, which is true
, meaning that the operation will attempt to demangle function names. Note that the object stackTrace
takes very little room on the stack, and by default allocates most of its memory directly from virtual memory without going through the heap, minimizing potential complications due to stack-size limits and possible heap corruption.
Finally, we use printFormatted
to stream out the stack-trace, one frame per line, in a concise, human-readable format.
The output from the preceding example on Solaris is as follows:
Notice that the lines have been truncated to fit this 79 column source file, and that on AIX or Windows, source file name and line number information will also be displayed.
In this example, we demonstrate obtaining return addresses from the stack using bsls::StackAddressUtil
, and later using them to load a balst::StackTrace
object with a description of the stack. This approach may be desirable if one wants to quickly save the addresses that are the basis for a stack-trace, postponing the more time-consuming translation of those addresses to more human-readable debug information until later. To do this, we create an array of pointers to hold the return addresses from the stack, which may not be desirable if we are in a situation where there isn't much room on the stack.
First, we define a routine recurseExample2
which will recurse the specified depth
times, then call traceExample2
.
Then, within traceExample2
, we create a stack-trace object and an array addresses
to hold some addresses.
Next, we call bsls::StackAddressUtil::getStackAddresses
to get the stored return addresses from the stack and load them into the array addresses
. The call returns the number of addresses saved into the array, which will be less than or equal to ARRAY_LENGTH
.
Then, we call loadStackTraceFromAddressArray
to initialize the information in the stack-trace object, such as function names, source file names, and line numbers, if they are available. The optional argument, demanglingPreferredFlag
, defaults to true
.
Finally, we can print out the stack-trace object using printFormatted
, or iterate through the stack-trace frames, printing them out one by one. In this example, we want instead to output only function names, and not line numbers, source file names, or library names, so we iterate through the stack-trace frames and print out only the properties we want. Note that if a string is unknown, it is represented as "", here we print it out as "--unknown--" to let the user see that the name was unresolved.
Running this example would produce the following output:
In this example, we demonstrate how to output return addresses from the stack to a stream in hex. Note that in this case the stack trace is never stored to a data object – when the operator<<
is passed a pointer to the hexStackTrace
function, it calls the hexStackTrace
function, which gathers the stack addresses and immediately streams them out. After the operator<<
is finished, the stack addresses are no longer stored anywhere.
First, we define a routine recurseExample3
which will recurse the specified depth
times, then call traceExample3
.
Finally, the output appears as a collection of hex values streamed out separated by spaces.
The hex stack traces can be translated to a human-readable stack trace using tools outside of BDE, such as Bloomberg's /bb/bin/showfunc.tsk
: