我有以下代码:
#include <stacktrace>
#include <iostream>
void bar() {
for (const auto &entry : std::stacktrace::current()) {
std::cout << entry << '\n';
}
}
void foo() {
bar();
}
int main() {
foo();
}
在调试构建中,这将打印出您期望的内容:
bar() at /app/example.cpp:5
foo() at /app/example.cpp:11
main at /app/example.cpp:15
at :0
_start at :0
但是,我并不完全确定这个无名的at :0
条目代表什么。真正令人困惑的是,当我们启用-O2
的优化时:
bar() at /app/example.cpp:5
foo() at /app/example.cpp:11
at :0
_start at :0
我不明白这个输出是怎么可能的,给定的汇编输出:
main:
sub rsp, 8
call bar()
xor eax, eax
add rsp, 8
ret
常见问题
1.如果foo()
是内联的,并且在调用链中完全跳过,那么bar()
如何知道堆栈跟踪是foo() -> bar()
?
1.如果bar()
以某种方式知道它的调用者--甚至是内联的调用者--为什么在启用优化时main
会从堆栈跟踪中消失呢?
1.那个没有名字的奇怪的at :0
条目是什么?有没有一种方法可以轻松地过滤掉它(不需要字符串操作)?
1条答案
按热度按时间gudnpqoy1#
堆栈跟踪旨在向您显示您处于哪个函数中,以及您如何到达那里。为此,这些函数的指令在内存中的位置并不重要-这就是内联所做的:它接受一个函数的指令,并将它们放入另一个函数的指令块中。但是,从逻辑上讲,您仍然处于已内联到另一个函数的函数中。这就是为什么stacktrace不考虑内联的实际答案:这不是人们在要求堆栈跟踪时感兴趣的东西。
从实际的Angular 来看,今天的编译器在很大程度上忽略了
inline
关键字,只是自己做决定。许多未标记为inline
的函数是内联的,而一些标记为inline
的函数则不是。如果堆栈跟踪会反映这一点,它们将是非常无用的,因为它们将反映 * 编译器的决定 *,而不是实际的代码结构。