I have a code snippet that is compiled with a debug build:
#include <stacktrace>
#include <iostream>
void bar() {
for (const auto &entry : std::stacktrace::current()) {
std::cout << entry << '\n';
}
}
void foo() {
bar();
}
int main() {
foo();
}
When compiled with a debug build, this code prints out the expected stack trace:
bar() at /app/example.cpp:5
foo() at /app/example.cpp:11
main at /app/example.cpp:15
at :0
_start at :0
However, when compiled with optimizations enabled (-O2
), the stack trace changes to:
bar() at /app/example.cpp:5
foo() at /app/example.cpp:11
at :0
_start at :0
The assembly output of the optimized build is:
main:
sub rsp, 8
call bar()
xor eax, eax
add rsp, 8
ret
See live example at Compiler Explorer
Questions
- How can
bar()
know that the stacktrace isfoo() -> bar()
iffoo()
is inlined, and completely skipped in the call chain? - If
bar()
somehow knows its callers -even the inlined ones-, how comemain
disappeared from the stacktrace when enabling optimizations? - What is the
at :0
entry with no name? Is there a way to easily filter it out (without string manipulation)?