c++ 11下C函数的错误码

error codes for C functions under C++11?

本文关键字:错误 误码 函数 11下 c++      更新时间:2023-10-16

我目前正在使用c++ 11下的C库,我现在面临的问题是我以前从未遇到过的,它以一种对我的程序的最终用户有意义的方式处理错误和失败。

目前在我的c++代码中有一些assert(foo()),其中foo是来自这个C库的函数,它返回一个反映操作状态的bool, true一切正常,false否则。

我想知道是否有更好的方法来处理这个问题,我想用一些自定义错误代码或不同的字符串/消息代替默认消息。还要注意,我不能修改这个库,所以任何可能的解决方案都需要考虑到这一点。

我关心的主要有两点:

  1. assert是当我在调试中编译我的代码时,我基本上不会在生产或发布模式中使用assert,也不会使用assert,就像我现在使用它一样
  2. 这个函数的很大一部分受到用户输入的高度影响,所以在运行时工作的东西是非常需要的。

我该怎么办?我基本上有一个返回bool的C函数,它不使用任何C或c++特定的错误处理函数或宏,我应该把它包装在try catch ?

我也考虑到这样一个事实,我想避免调用std::abort,我更愿意在失败的情况下清理一切。

我会用c++ 异常

您可以使用一些已经定义的标准c++异常类,如std::runtime_error,或者您可以定义一些自定义异常类(例如从std::runtime_error派生)。

// FooWrapper.h  --  C++ wrapper around your "foo" library
#pragma once
#include <stdexcept>  // For std::runtime_error
#include "foo.h"      // The C library header
...
namespace Foo {  // Can wrap the raw C library nicely in a namespace

// Custom exception class for your "foo" errors.
class FooError : public std::runtime_error {
public:
    explicit FooError(const std::string& errorMessage) 
        : std::runtime_error(errorMessage) { 
       // Can do additional initialization stuff, and pass
       // additional information regarding the particular "Foo" error,
       // e.g. as another constructor parameter.
       // ...
    }
};
... other stuff in the wrapping header ...
} // namespace Foo

然后,在c++代码中,当foo()函数调用失败时,您可以throw上述异常:

if (! foo()) {
    throw Foo::FooError("Some information", ...some other error params... );
}

,你可以catch,并尝试恢复或打印一个漂亮的错误信息在你的代码的GUI部分,例如:

try {
     // ... do something ...
} catch( const Foo::FooError& fooError ) {
    // ... try to recover, or display the error message 
    // returned by fooError.what()
}

还请注意,由于FooError异常类被插入到标准的c++异常层次结构中(因为它派生自std::runtime_error),这个自定义异常也可以被代码库中已经存在的c++代码捕获,它试图捕获更通用的std::runtime_errorstd::exception类。

按照您的建议,将代码中库的所有入口点放在try/catch块中。那么最快最简单的解决方法就是

if (!foo())
    throw std::runtime_error("foo(): returned false");

。当你决定需要更结构化的行为时,你可以创建自己的异常类(可能但不一定是从std::exception派生的),例如,依赖于确切哪个函数失败的行为。在简单的情况下,你只需要输入

try
{
   ... //The if/throw test will typically not occur here, but deeper within the call stack.
}
catch (std::exception& e)
{
   std::cerr << e.what() << std::endl;
   //do cleanup
}

之类的。编辑:正如@TNA所强调的,你把try/catch块放在代码中你能够处理错误的地方。if/throw测试可以在任何地方进行。

如果可以考虑宏和go to语句,我认为这可以是另一种选择:

#define CHECK (fn) if (!fn) 
{ 
// Set the valid error msg somewhere  that can be retrieved later on..
 goto QUIT; 
} 
// Usage
AnyObject Afnc()
{
AnyObject anyObj;
CHECK(foo())

QUIT: 
 return anyObj;

}