【发布时间】:2015-06-23 10:27:56
【问题描述】:
在我的代码中,我抛出了源自 std::runtime_error 的自定义 file_error 异常。在另一个模块中,我捕获该操作的异常并希望像这样处理我的 file_error:
try
{
base::create_directory(INVALID_NAME, 0700);
...
}
catch (const base::file_error &exc)
{
...
}
catch(std::runtime_error &exc)
{
...
}
catch(std::exception &exc)
{
...
}
file_error 声明为:
namespace base {
class file_error : public std::runtime_error
{
int sys_error_code;
public:
file_error(const std::string &text, int err);
error_code code();
int sys_code();
};
}
然而,file_error 的 catch 分支永远不会被触发。要么我在 runtime_error 分支中结束,要么,如果我删除它,在异常分支中。
但是,这在 Linux + Win (gcc, VS) 中可以正常工作,而在 Mac (clang) 上则无法正常工作。知道这里可能出了什么问题吗?
更新:
这是我到达 runtime_error 分支时的 lldb 输出:
(lldb) p exc
(const base::file_error) $0 = {
std::runtime_error = {
__imp_ = (__imp_ = 0x0000000000000000)
}
sys_error_code = 13923331
}
这清楚地表明异常确实是 base::file_error 类型。它只是没有被其关联的 catch 块捕获。
更新 2:
在与上面的测试代码相同的文件中根据file_error声明自己的错误,如下所示:
class test_error : base::file_error {
public:
test_error(const std::string &s) : base::file_error(s, 0) {};
};
允许我在 test_error 块和 catch-all 块中捕获它,但不能在 base::file_error、std::runtime_error 或 std::exception 块中捕获。很奇怪。
更新 3:
经过大量试验,我现在认为这是一个类型不匹配的问题,类似于 ODR 违规,但类型不同。 dylib 和测试应用程序中的类型不被认为是相同的,因此不会捕获异常,除非我直接在测试代码中抛出那个 base::file_error 异常。
【问题讨论】:
-
这可能表明您违反了 ODR:
base::runtime_error的多个定义被应用程序的不同部分使用。 -
不,我检查了所有代码。只有一个定义存在。
-
尝试使用带有
--detect-odr-violations命令行选项的gold链接。 -
为什么它会在调试器中显示为
const,而您的异常处理程序通过引用非常量捕获异常? -
那只是因为我尝试了各种组合并且不想不断更新问题文本。最初的 catch 块是为
(const base::file_error &exc)。
标签: c++ exception exception-handling clang