c++ 内联函数出现在std::stacktrace中,但main不出现

t9aqgxwy  于 2023-06-25  发布在  其他
关注(0)|答案(1)|浏览(119)

我有以下代码:

#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条目是什么?有没有一种方法可以轻松地过滤掉它(不需要字符串操作)?

gudnpqoy

gudnpqoy1#

堆栈跟踪旨在向您显示您处于哪个函数中,以及您如何到达那里。为此,这些函数的指令在内存中的位置并不重要-这就是内联所做的:它接受一个函数的指令,并将它们放入另一个函数的指令块中。但是,从逻辑上讲,您仍然处于已内联到另一个函数的函数中。这就是为什么stacktrace不考虑内联的实际答案:这不是人们在要求堆栈跟踪时感兴趣的东西。
从实际的Angular 来看,今天的编译器在很大程度上忽略了inline关键字,只是自己做决定。许多未标记为inline的函数是内联的,而一些标记为inline的函数则不是。如果堆栈跟踪会反映这一点,它们将是非常无用的,因为它们将反映 * 编译器的决定 *,而不是实际的代码结构。

相关问题