【发布时间】:2019-01-24 11:10:42
【问题描述】:
我正在使用 Visual C++ 2017 编译以下代码(已启用 C++17 功能)
int main() {
try {
// loot is some library that is linked as a dll
auto game = loot::CreateGameHandle(loot::GameType::fonv, "c:\\something\\invalid", "C:\\something\\invalid");
// throw std::invalid_argument("this works as expected");
}
catch (const std::exception &e) {
std::cout << "caught as exception " << e.what() << std::endl;
}
catch (const std::invalid_argument &e) {
std::cout << "caught as invalid_argument " << e.what() << std::endl;
}
catch (...) {
std::cout << "caught by ..." << std::endl;
}
}
编译器按预期报告:
warning C4286: 'const std::invalid_argument &': is caught by base class ('const stdext::exception &') on line 8
但是,应用程序的输出是
caught as invalid_argument Given game path "c:\something\invalid" does not resolve to a valid directory.
而且它不只是改变捕获顺序或其他东西,如果我删除最后 2 个捕获块,应用程序会因为未处理的异常而崩溃。
这怎么可能?我假设这在某种程度上与编译器设置有关,这些设置使 my std::exception 与库中的一个 std::invalid_argument 继承自不同的类型 - 但为什么 my std::invalid_argument 与他们的类型相同? 有没有办法解决这个问题?因为那个库抛出了很多不同的异常类型,而我无法真正单独捕获每一个。
【问题讨论】:
-
这听起来很奇怪。你能用minimal reproducible example 重现这个吗?我知道这会很困难。
-
您应该始终从最具体的例外开始。那么
loot也是用VS2017编译的吗?当库抛出的异常由于运行时不匹配而未被其他代码捕获时,我看到了问题。 -
它说
stdext::exception是一个很大的危险信号。这里有些不正常。 -
dll是用同一个系统运行时编译的吗?
-
是的,战利品也是用 VS2017 构建的,但不确定它是否是完全相同的版本。这还重要吗? stdext::exception 是什么意思? Afaict 所有 std 异常都在 Visual Studio 的该命名空间中声明,然后使用 using 子句包含在 std 中。