C++ C++;11(或Boost)系统错误策略

C++ C++;11(或Boost)系统错误策略,c++,boost,c++11,system-error,C++,Boost,C++11,System Error,我正在开发一个系统,该系统被设计为使用名为error\u code、error\u condition和error\u category的类,这是C++11中的一个新方案,尽管目前我实际上正在使用Boost实现。我已经读了Chris Kholkoff的书三遍了,我想我基本上理解了如何创建这些类 我的问题是,这个系统需要处理存在于单个DLL中的插件,这些插件可能会出现错误。我最初的设计是规划一个特定于系统的错误类别,该类别将包含所有不同的错误代码和一个特定错误条件的短列表,这些错误条件实际上没有映

我正在开发一个系统,该系统被设计为使用名为
error\u code
error\u condition
error\u category
的类,这是C++11中的一个新方案,尽管目前我实际上正在使用Boost实现。我已经读了Chris Kholkoff的书三遍了,我想我基本上理解了如何创建这些类

我的问题是,这个系统需要处理存在于单个DLL中的插件,这些插件可能会出现错误。我最初的设计是规划一个特定于系统的错误类别,该类别将包含所有不同的错误代码和一个特定错误条件的短列表,这些错误条件实际上没有映射到
errno
值。这里的问题是,为了使DLL能够使用其中一个错误代码,它需要访问应用程序中
error\u类别
的唯一实例。我现在通过从每个DLL导出一个
SetErrorCategory()
函数来处理这个问题,这个函数可以工作,但有点麻烦

我看到的另一种解决方案是,每个DLL都有自己的错误类别和代码,如果需要,还有自己的条件;我怀疑这更像是对这个库特性的设想。但是,我认为这需要在主应用程序的错误方案中使用一个比较函数,该函数知道插件的错误方案,并可以检查应用程序的哪些条件与插件的错误匹配。这似乎更容易出现一系列问题,尽管我还没有尝试实现它。我猜我必须在所有实际逻辑的基础上,从DLL导出整个错误方案

当然,另一种方法是只使用DLL中的数字错误代码,并将它们填充到应用程序端的错误对象中。它的优点是插件简单,但可能会导致应用程序中出现问题(例如,一个函数处理来自两个不同插件的对象时需要注意每个错误的来源)


所以我的具体问题是:在这三个选项中,你会使用哪一个,为什么?这显然是行不通的?当然,还有一种更好的方法没有出现在我的脑海中吗?

我在处理这个问题时找到的解决方案是,对问题家族使用预定义代码,对用户子代码进行选择,并对特定类型的错误进行继承。通过boost,我可以通过以下方式继承特定类型:

struct IOException : virtual std::exception, virtual boost::exception {};
struct EOFException : IOException {};
...
并使错误代码与预定义的常规错误(如IOException)匹配。因此,我可以为每个错误系列提供一个通用代码范围:

namespace exception { namespace code {
    UNKNOWN_EXCEPTION           = 0;
    IO_EXCEPTION                = 100;
    CONCURRENCY_EXCEPTION       = 200;
    ...
}}
然后,如果有人想要一个新的错误类型,他们可以从已经定义的泛型异常类型和伴随该错误的代码继承,并通过继承类型和次要值(0-99)专门化异常。这还允许try-catch块捕获更具体的错误类型,同时将更通用的异常版本传递给其他控制块。然后,用户可以自由使用父异常代码或指定其自己在族中的代码(parent=100->child=115)。如果用户只是想要一个IOError,而不需要创建新的错误族,那么他们可以轻松地使用默认的族异常。我发现这给了用户灵活性,当他们不需要时,不需要OCD跟踪异常代码


然而,这并不是最终的解决方案,因为个人偏好导致了我在这里的设计选择。我发现错误代码太多会让人困惑,异常继承已经对这些信息进行了编码。实际上,在我描述的系统中,完全剔除错误代码很容易,只需依赖异常继承,但许多人更喜欢为每个异常名称分配一个代码。

我想出了另一个解决方案:创建一个只包含我的
错误类别的DLL
实现,并从应用程序和每个插件DLL链接到它。这使他们能够访问全局类别对象,而不必显式地将该对象从应用程序传递到DLL。

C++无法跨DLL边界正常工作--请注意,如果您决定将异常从一个抛出到另一个,您将失去DLL提供的大部分可重用性,因为只有当使用者使用与DLL相同的编译器、相同的编译器版本和相同的编译器开关构建时,才会以定义良好的方式加载DLL。你提到克里斯·霍尔科夫(Chris Kholkoff)的系列文章,我最近刚刚读过,最后一篇暗示将有第6部分。然而,2010年4月是最后一篇博客。他曾经制作过第六部分吗?如果是的话,我在哪里可以找到它?@StoneFree:据我所知,他没有。我想我解释得很糟糕。我使用的类称为
error\u code
error\u condition
,和
error\u category
——这与异常类无关。我会修改的。好的,我会留下我的答案,因为它与你真正想要的有关