BDE 4.14.0 Production release
Loading...
Searching...
No Matches
balst_stacktrace

Detailed Description

Outline

Purpose

Provide a description of a function-call stack.

Classes

See also
balst_stacktraceframe, balst_stacktraceutil, balst_stacktraceprintutil, bdlma_heapbypassallocator

Description

This component provides a (value-semantic) container class, balst::StackTrace, that is used to describe a function-call stack. A stack-trace object contains a sequence of balst::StackTraceFrame objects. By default, a balst::StackTrace object is supplied memory by an owned bdlma::HeapBypassAllocator object, though the client may specify another allocator at construction to be used in its place.

Usage

This section illustrates intended use of this component.

Example 1: Configuring a Stack-Trace Value

In this example we demonstrate how to create a balst::StackTrace object, and then to both modify and access its value.

First, we set up a test allocator as default allocator. A balst::StackTrace object, by default, gets all its memory from an owned bdlma::HeapBypassAllocator object. To demonstrate this default behavior we start by setting the default allocator to a test allocator so we can verify later that it was unused:

Definition bslma_defaultallocatorguard.h:186
Definition bslma_testallocator.h:384

Then, we create a stack-trace object. Note that when we don't specify an allocator, the default allocator is not used – rather, a heap-bypass allocator owned by the stack-trace object is used. The heap-bypass allocator is recommended because this component is often used to obtain debug information in situations where an error has occurred, and the possibility of heap corruption can't be ruled out. The heap-bypass allocator obtains its memory directly from virtual memory rather than going through the heap, avoiding potential complications due to heap corruption.

balst::StackTrace stackTrace;
assert(0 == stackTrace.length());
Definition balst_stacktrace.h:206
int length() const
Return the number of stack-trace frames contained in this object.
Definition balst_stacktrace.h:435

Next, we resize the stack-trace object to contain two default-constructed frames, and take references to each of the two new frames:

stackTrace.resize(2);
assert(2 == stackTrace.length());
balst::StackTraceFrame& frame0 = stackTrace[0];
balst::StackTraceFrame& frame1 = stackTrace[1];
Definition balst_stacktraceframe.h:222
void resize(int newLength)
Definition balst_stacktrace.h:407

Then, we set the values of the fields of the two new frames.

frame0.setAddress((void *) 0x12ab);
frame0.setLibraryFileName("/a/b/c/balst_stacktrace.t.dbg_exc_mt");
frame0.setLineNumber(5);
frame0.setOffsetFromSymbol(116);
frame0.setSourceFileName("/a/b/c/sourceFile.cpp");
frame0.setMangledSymbolName("_woof_1a");
frame0.setSymbolName("woof");
frame1.setAddress((void *) 0x34cd);
frame1.setLibraryFileName("/lib/libd.a");
frame1.setLineNumber(15);
frame1.setOffsetFromSymbol(228);
frame1.setSourceFileName("/a/b/c/secondSourceFile.cpp");
frame1.setMangledSymbolName("_arf_1a");
frame1.setSymbolName("arf");
void setLineNumber(int value)
Definition balst_stacktraceframe.h:575
void setOffsetFromSymbol(bsl::size_t value)
Definition balst_stacktraceframe.h:591
void setAddress(const void *value)
Definition balst_stacktraceframe.h:561
void setSymbolName(const bsl::string_view &value)
Definition balst_stacktraceframe.h:605
void setMangledSymbolName(const bsl::string_view &value)
Definition balst_stacktraceframe.h:583
void setLibraryFileName(const bsl::string_view &value)
Definition balst_stacktraceframe.h:567
void setSourceFileName(const bsl::string_view &value)
Definition balst_stacktraceframe.h:597

Next, we verify the frames have the values we expect:

assert((void *) 0x12ab == frame0.address());
assert("/a/b/c/balst_stacktrace.t.dbg_exc_mt"
== frame0.libraryFileName());
assert( 5 == frame0.lineNumber());
assert(116 == frame0.offsetFromSymbol());
assert("/a/b/c/sourceFile.cpp" == frame0.sourceFileName());
assert("_woof_1a" == frame0.mangledSymbolName());
assert("woof" == frame0.symbolName());
assert((void *) 0x34cd == frame1.address());
assert("/lib/libd.a" == frame1.libraryFileName());
assert( 15 == frame1.lineNumber());
assert(228 == frame1.offsetFromSymbol());
assert("/a/b/c/secondSourceFile.cpp" == frame1.sourceFileName());
assert("_arf_1a" == frame1.mangledSymbolName());
assert("arf" == frame1.symbolName());
int lineNumber() const
Definition balst_stacktraceframe.h:626
const bsl::string & mangledSymbolName() const
Definition balst_stacktraceframe.h:638
const bsl::string & libraryFileName() const
Definition balst_stacktraceframe.h:620
const bsl::string & symbolName() const
Definition balst_stacktraceframe.h:650
const bsl::string & sourceFileName() const
Definition balst_stacktraceframe.h:644
bsl::size_t offsetFromSymbol() const
Definition balst_stacktraceframe.h:632
const void * address() const
Definition balst_stacktraceframe.h:614

Next, we output the stack-trace object:

stackTrace.print(cout, 1, 2);
bsl::ostream & print(bsl::ostream &stream, int level=0, int spacesPerLevel=4) const

Finally, we observe the default allocator was never used.

assert(0 == da.numAllocations());
bsls::Types::Int64 numAllocations() const
Definition bslma_testallocator.h:1081

The above usage produces the following output:

[
[
address = 0x12ab
library file name = "/a/b/c/balst_stacktrace.t.dbg_exc_mt"
line number = 5
mangled symbol name = "_woof_1a"
offset from symbol = 116
source file name = "/a/b/c/sourceFile.cpp"
symbol name = "woof"
]
[
address = 0x34cd
library file name = "/lib/libd.a"
line number = 15
mangled symbol name = "_arf_1a"
offset from symbol = 228
source file name = "/a/b/c/secondSourceFile.cpp"
symbol name = "arf"
]
]