Quick Links:

bal | bbl | bdl | bsl

Namespaces

Component balst_stacktraceprinter
[Package balst]

Provide an object for streaming the current stack trace. More...

Namespaces

namespace  balst

Detailed Description

Outline
Purpose:
Provide an object for streaming the current stack trace.
Classes:
balst::StackTracePrinter object for streaming the current stack trace
See also:
Component 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:
  BALL_LOG_SET_NAMESPACE_CATEGORY("MY.CATEGORY");

  void recurseAndStreamStackDefault()
      // Recurse 4 times and print a stack trace to 'BALL_LOG_FATAL'.
  {
      static int recurseCount = 0;

      if (recurseCount++ < 4) {
          recurseAndStreamStackDefault();
      }
      else {
          BALL_LOG_FATAL << balst::StackTracePrinter();
      }
  }
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()
      // Recurse 4 times and print a stack trace to 'BALL_LOG_FATAL'.
  {
      static int recurseCount = 0;

      if (recurseCount++ < 4) {
          recurseAndStreamStackMaxFrames2();
      }
      else {
          BALL_LOG_FATAL << balst::StackTracePrinter(2);
      }
  }
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()
      // Recurse 4 times and print a stack trace to 'BALL_LOG_FATAL'.
  {
      static int recurseCount = 0;

      if (recurseCount++ < 4) {
          recurseAndStreamStackNoDemangle();
      }
      else {
          BALL_LOG_FATAL << balst::StackTracePrinter(-1, false);
      }
  }
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()
      // Recurse 4 times and print a stack trace to 'BALL_LOG_FATAL'.
  {
      static int recurseCount = 0;

      if (recurseCount++ < 4) {
          recurseAndStreamStackAddIgnore5();
      }
      else {
          BALL_LOG_FATAL << balst::StackTracePrinter(-1, true, 5);
      }
  }
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