gpt4 book ai didi

c++ - 未捕获的 std::exception 在核心中不正确的堆栈跟踪

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:56:23 25 4
gpt4 key购买 nike

这是我的代码:

#include <string>
#include <tr1/functional>

using namespace std;
using namespace std::tr1;
using namespace std::tr1::placeholders;

class Event
{
public:
typedef std::tr1::function<void()> Handler;

void set(Handler h)
{
m_handler = h;
}

template<typename T, typename F>
void set(T * obj, F memfn)
{
set(std::tr1::bind(memfn, obj));
}

void operator()()
{
m_handler();
}

static void fire(Event * event) throw ()
{
(*event)();
}

Handler m_handler;
};

class BuggyHandler
{
public:

BuggyHandler()
{
}

BuggyHandler(Event * b) :
bar(b)
{
bar->set(this, &BuggyHandler::HandleEvent);
}

void HandleEvent()
{
// throw std::length_error
std::string().append(std::numeric_limits<size_t>::max(), '0');
}

private:

Event * bar;
};

void get_correct_stacktrace()
{
Event bar;
BuggyHandler handler(&bar);
bar();
}

void get_incorrect_stacktrace()
{
Event bar;
BuggyHandler handler(&bar);
Event::fire(&bar);
}

int main(int argc, char **argv)
{
int opt = atoi(argv[1]);
if (opt)
get_correct_stacktrace();
else
get_incorrect_stacktrace();
}

当我调用 ./test 1 时,我可以从核心获得正确的堆栈跟踪:

#0  0xffffe410 in __kernel_vsyscall ()
#1 0xf7d028d0 in raise () from /lib/libc.so.6
#2 0xf7d03ff3 in abort () from /lib/libc.so.6
#3 0xf7ede880 in __gnu_cxx::__verbose_terminate_handler () from /usr/lib/libstdc++.so.6
#4 0xf7edc2a5 in std::exception::what () from /usr/lib/libstdc++.so.6
#5 0xf7edc2e2 in std::terminate () from /usr/lib/libstdc++.so.6
#6 0xf7edc41a in __cxa_throw () from /usr/lib/libstdc++.so.6
#7 0xf7e73c6f in std::__throw_length_error () from /usr/lib/libstdc++.so.6
#8 0xf7eb9a17 in std::string::append () from /usr/lib/libstdc++.so.6
#9 0x08049b96 in BuggyHandler::HandleEvent (this=0xffc26c9c) at /home/liangxu/release/server_2.0/test/src/test.cc:54
#10 0x08049857 in get_correct_stacktrace () at /home/liangxu/release/server_2.0/test/src/test.cc:67
#11 0x080498e0 in main (argc=Cannot access memory at address 0x5ac6) at /home/liangxu/release/server_2.0/test/src/test.cc:81

抛出异常的位置是test.cc:54

当我调用 ./test 0 时,我可以从核心获取不正确的堆栈跟踪:

#0  0xffffe410 in __kernel_vsyscall ()
#1 0xf7d508d0 in raise () from /lib/libc.so.6
#2 0xf7d51ff3 in abort () from /lib/libc.so.6
#3 0xf7f2c880 in __gnu_cxx::__verbose_terminate_handler () from /usr/lib/libstdc++.so.6
#4 0xf7f2a2a5 in std::exception::what () from /usr/lib/libstdc++.so.6
#5 0xf7f2a2e2 in std::terminate () from /usr/lib/libstdc++.so.6
#6 0xf7f2a305 in std::exception::what () from /usr/lib/libstdc++.so.6
#7 0xf7f29d98 in __cxa_call_unexpected () from /usr/lib/libstdc++.so.6
#8 0x080497eb in get_incorrect_stacktrace () at /home/liangxu/release/server_2.0/test/src/test.cc:30
#9 0x080498f5 in main (argc=Cannot access memory at address 0x5adf) at /home/liangxu/release/server_2.0/test/src/test.cc:83

没有抛出异常的位置。

我的编译器是“gcc (GCC) 4.1.2 20070115 (prerelease) (SUSE Linux)”

如果使用“-fno-exceptions”编译,两种方法都会生成正确的堆栈跟踪。

这是什么原因?

最佳答案

两个堆栈跟踪都是正确的。

当您调用 Event::fire 时, 异常抛出在 HandleEvent并且堆栈展开发生直到它遇到 fire它具有那个异常规范。

如果您不知道异常规范的真实行为,您可以在这里阅读:http://www.gotw.ca/publications/mill22.htm

基本上,规范throw ()如果其中一个包含调用抛出,则确实保证此方法不会因悲惨地失败而抛出。当堆栈展开试图退出此方法时,它会检查异常规范,发现它不匹配,然后调用 std::unexpected从展开的当前位置,因此 __cxa_call_unexpected ()get_incorrect_stacktrace () 之后的堆栈跟踪中.

在大多数情况下,在 C++ 中使用异常规范是无用的,因为提供保证的代价是程序的一般失败是抛出而不应该抛出的东西。

关于c++ - 未捕获的 std::exception 在核心中不正确的堆栈跟踪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8738301/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com