如何解决为什么只有当异常转义了当前函数时,std :: function才会导致取消堆栈的堆栈?
我正在尝试解决this std::thread bug的问题,这会通过应用noexcept
批注来使堆栈在旧版本的gcc中解开:
#include <functional>
#include <stdexcept>
void thrower() {
throw std::runtime_error("A message is useful but where's my stack?");
}
void run() {
// Culprit:
auto j = std::function<void()>([] { thrower(); });
// Works fine:
// auto j = [] { thrower(); };
j();
}
void wrap() noexcept {
run();
// Works fine too:
// auto j = std::function<void()>([] { thrower(); });
// j();
}
int main() {
wrap();
}
由于run
函数在库中,因此我需要将noexcept
应用于包装函数wrap
。但是,我观察到,当run
函数使用std::function
时,堆栈仍处于部分展开状态,并且我看不到关键点告诉我该异常起源于thrower
:
#0 0x000000000041fb41 in raise ()
#1 0x0000000000401b30 in abort ()
#2 0x00000000004012cb in __gnu_cxx::__verbose_terminate_handler() [clone .cold] ()
#3 0x0000000000403876 in __cxxabiv1::__terminate(void (*)()) ()
#4 0x0000000000414d69 in __cxa_call_terminate ()
#5 0x0000000000403531 in __gxx_personality_v0 ()
#6 0x0000000000416fbe in _Unwind_RaiseException_Phase2 ()
#7 0x0000000000417ab6 in _Unwind_Resume ()
#8 0x0000000000402668 in std::function<void ()>::~function() (this=<optimized out>,__in_chrg=<optimized out>)
at /usr/include/c++/10/bits/std_function.h:303
#9 run () at main.cpp:10
#10 0x0000000000402671 in wrap () at main.cpp:17
#11 0x000000000040267f in main () at main.cpp:24
请注意第7帧中的_Unwind_Resume
和第8帧中的std::function
析构函数(后者在gcc 7中也看到了,但在gcc 10中,我必须设置优化级别进行调试才能看到它)。
std::function
会导致堆栈解绕,而为什么lambda不会发生这种情况?标准允许吗?我对取消交易的规则了解不多,所以请向我推荐相关资源。
假设我无法修改run
,我该怎么做以防止堆栈散开?
更多实验:
如果我改用lambda,我会看到thrower
,而不是_Unwind_Resume
,而是_Unwind_RaiseException
:
... (as above) ...
#6 0x0000000000416e5e in _Unwind_RaiseException_Phase2 ()
#7 0x0000000000417630 in _Unwind_RaiseException ()
#8 0x00000000004036c8 in __cxa_throw ()
#9 0x0000000000402575 in thrower () at main.cpp:5
#10 0x0000000000402591 in operator() (__closure=<synthetic pointer>) at main.cpp:13
#11 run () at main.cpp:13
#12 0x000000000040259a in wrap () at main.cpp:17
#13 0x00000000004025a3 in main () at main.cpp:24
如果我将run
的主体复制到wrap
中,堆栈也就完整了,因此问题似乎专门与调用std::function
的转义函数引发的异常有关 not 带有noexcept
注释。
... (as above) ...
#11 std::__invoke_impl<void,wrap()::<lambda()>&> (__f=...) at /usr/include/c++/10/bits/invoke.h:60
#12 std::__invoke_r<void,wrap()::<lambda()>&> (__fn=...) at /usr/include/c++/10/bits/invoke.h:153
#13 std::_Function_handler<void(),wrap()::<lambda()> >::_M_invoke(const std::_Any_data &) (__functor=...)
at /usr/include/c++/10/bits/std_function.h:291
#14 0x0000000000402680 in std::function<void ()>::operator()() const (this=this@entry=0x7fffffffd780)
at /usr/include/c++/10/bits/std_function.h:248
#15 0x0000000000402641 in wrap () at main.cpp:20
#16 0x0000000000402667 in main () at main.cpp:24
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。