基类未捕获 C++ 异常

Posted

技术标签:

【中文标题】基类未捕获 C++ 异常【英文标题】:C++ Exception not caught by base class 【发布时间】: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 中。 【参考方案1】:

该死的,对不起。 事实证明,我使用的构建系统将 _HAS_EXCEPTIONS=0 添加到了预处理器定义中。这就是造成这种情况的原因。

【讨论】:

以上是关于基类未捕获 C++ 异常的主要内容,如果未能解决你的问题,请参考以下文章

错误 C2504:'BASECLASS':基类未定义

基类未定义,但包含其标头

仅在运行单元测试时出现 OLE DB 异常“类未注册”

CArray<TYPE,ARG_TYPE>' : 基类未定义

Qt - moc 导致 C2504:基类未定义

带有前向声明的循环包含和继承导致 C2504 基类未定义