C++ 无法捕获自定义std::runtime\u错误

C++ 无法捕获自定义std::runtime\u错误,c++,exception,exception-handling,clang,C++,Exception,Exception Handling,Clang,在我的代码中,我抛出我的自定义文件错误异常,它是从std::runtime\u error派生的。在另一个模块中,我捕获该操作的异常,并希望像这样处理我的文件错误: try { base::create_directory(INVALID_NAME, 0700); ... } catch (const base::file_error &exc) { ... } catch(std::runtime_error &exc) { ... } catch(std

在我的代码中,我抛出我的自定义文件错误异常,它是从std::runtime\u error派生的。在另一个模块中,我捕获该操作的异常,并希望像这样处理我的文件错误:

try
{
  base::create_directory(INVALID_NAME, 0700);
  ...
}
catch (const base::file_error &exc)
{
   ...
}
catch(std::runtime_error &exc)
{
    ...
}
catch(std::exception &exc)
{
  ...
}
class test_error : base::file_error {

public:
  test_error(const std::string &s) : base::file_error(s, 0) {};
};
文件错误声明为:

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();
};
}
但是,永远不会触发文件_错误的catch分支。我要么在运行时错误分支中结束,要么在异常分支中结束(如果删除该分支)

然而,这在Linux+Win(gcc,VS)中运行良好,而在Mac(clang)上则不起作用。你知道这里有什么问题吗

更新:

以下是我到达运行时错误分支时的lldb输出:

(lldb) p exc
(const base::file_error) $0 = {
  std::runtime_error = {
    __imp_ = (__imp_ = 0x0000000000000000)
  }
  sys_error_code = 13923331
}
这清楚地表明异常确实属于base::file\u error类型。它只是在关联的catch块中没有被捕获

更新2:

基于与上面的测试代码位于同一文件中的file_error声明自己的错误,如下所示:

try
{
  base::create_directory(INVALID_NAME, 0700);
  ...
}
catch (const base::file_error &exc)
{
   ...
}
catch(std::runtime_error &exc)
{
    ...
}
catch(std::exception &exc)
{
  ...
}
class test_error : base::file_error {

public:
  test_error(const std::string &s) : base::file_error(s, 0) {};
};
允许我在test_错误块和catch all块中捕获它,但不能在base::file_错误、std::runtime_错误或std::exception块中捕获它。奇怪

更新3:

经过大量的实验,我现在认为这是一个类型不匹配的问题,类似于ODR冲突,但类型不同。dylib和测试应用程序中的类型不被认为是相同的,因此不会捕获异常,除非我在测试代码中直接抛出base::file_错误验证

class test_error : base::file_error 
允许我在test_错误块和catch all块中捕获它,但不能在base::file_错误、std::runtime_错误或std::exception块中捕获它

您的异常类需要从基本异常类公开派生。否则,您将无法通过基类捕获它们:

class test_error : public base::file_error 

此问题的解决方案是避免在测试应用程序中使用编译器选项
-fvisibility=hidden
(或将其设为默认值)。请在此处阅读更多信息:。特别是本部分:

注意,F可视性影响C++模糊链接实体。这 意味着,例如,在 DSO必须明确标记为默认可见性,以便 “type_info”节点在DSO之间统一

下面简要介绍这些技术、它们的优点以及如何使用它们 在


这可能表明您存在ODR冲突:应用程序的不同部分使用了
base::runtime\u error
的多个定义。不,我检查了所有代码。只有一个定义存在。请尝试使用gold与
--检测odr冲突
命令行选项链接。为什么它在调试器中显示为
const
,而您的异常处理程序通过引用非const捕获异常?这只是因为我尝试了各种组合,不想不断更新问题文本。最初,catch块用于
(const base::file\u error&exc)
。捕捉得好。这至少解释了为什么我不能将测试错误捕获为file_error,现在它可以工作了。只是最初的问题仍然悬而未决。