将 errno 转换为退出代码
Convert errno to exit codes
我正在开发使用大量文件系统函数的库。
我想要的是我的函数 returns 各种 错误代码 (不仅仅是 -1 作为错误)取决于 errno 以防文件系统功能失效。
虽然我可以直接使用 errno 值,但我想在我的函数 error codes 和 [=26= 之间创建一些抽象层]system errno(例如,我的错误值从 -1000 开始并且是负数,而 errno 值是正数)。
我的问题是什么是最好的实施方式。
现在我看到两个可能的解决方案:
- 使用带有错误代码的枚举和 switch case 函数进行翻译,例如:
typedef enum {
MY_ERROR_EPERM = -1104, /* Operation not permitted */
MY_ERROR_ENOENT = -1105, /* No such file or directory */
// ...
} MyReturnCodes_t;
int ErrnoToErrCode(unsigned int sysErrno) {
int error = ENOSYS;
switch(sysErrno) {
case EPERM: error = MY_ERROR_EPERM; break;
case ENOENT: error = MY_ERROR_ENOENT; break;
// ...
}
return error;
}
- 直接在枚举中使用翻译:
#define ERR_OFFSET -1000
typedef enum {
MY_ERROR_EPERM = ERR_OFFSET - EPERM, /* Operation not permitted */
MY_ERROR_ENOENT = ERR_OFFSET - ENOENT, /* No such file or directory */
MY_ERROR_ESRCH = ERR_OFFSET - ESRCH, /* No such process */
// ...
} MyReturnCodes_t;
哪种方式更稳定?
还有一点:这个库应该在QNX和LinuxOS上都用,what是对齐 errno 代码的正确方法(在某些情况下不同)?
我会选择一个 std::map
的专用函数。只要使用提供的错误宏,您就不必关心差距或任何事情:
#include <iostream>
#include <errno.h>
#include <map>
namespace MyError
{
enum MyReturnCode: int
{
MY_INVALID_VAL = 0 , /* Invalid Mapping */
MY_ERROR_EPERM = -1104, /* Operation not permitted */
MY_ERROR_ENOENT = -1105, /* No such file or directory */
};
MyReturnCode fromErrno(int e)
{
static const std::map<int, MyReturnCode> mapping {
{ EPERM, MY_ERROR_EPERM},
{ ENOENT, MY_ERROR_ENOENT}
};
if(mapping.count(e))
return mapping.at(e);
else
return MY_INVALID_VAL;
}
}
int main()
{
std::cout << MyError::fromErrno(ENOENT) << std::endl;
std::cout << MyError::fromErrno(42) << std::endl;
return 0;
}
我正在开发使用大量文件系统函数的库。
我想要的是我的函数 returns 各种 错误代码 (不仅仅是 -1 作为错误)取决于 errno 以防文件系统功能失效。
虽然我可以直接使用 errno 值,但我想在我的函数 error codes 和 [=26= 之间创建一些抽象层]system errno(例如,我的错误值从 -1000 开始并且是负数,而 errno 值是正数)。
我的问题是什么是最好的实施方式。
现在我看到两个可能的解决方案:
- 使用带有错误代码的枚举和 switch case 函数进行翻译,例如:
typedef enum {
MY_ERROR_EPERM = -1104, /* Operation not permitted */
MY_ERROR_ENOENT = -1105, /* No such file or directory */
// ...
} MyReturnCodes_t;
int ErrnoToErrCode(unsigned int sysErrno) {
int error = ENOSYS;
switch(sysErrno) {
case EPERM: error = MY_ERROR_EPERM; break;
case ENOENT: error = MY_ERROR_ENOENT; break;
// ...
}
return error;
}
- 直接在枚举中使用翻译:
#define ERR_OFFSET -1000
typedef enum {
MY_ERROR_EPERM = ERR_OFFSET - EPERM, /* Operation not permitted */
MY_ERROR_ENOENT = ERR_OFFSET - ENOENT, /* No such file or directory */
MY_ERROR_ESRCH = ERR_OFFSET - ESRCH, /* No such process */
// ...
} MyReturnCodes_t;
哪种方式更稳定?
还有一点:这个库应该在QNX和LinuxOS上都用,what是对齐 errno 代码的正确方法(在某些情况下不同)?
我会选择一个 std::map
的专用函数。只要使用提供的错误宏,您就不必关心差距或任何事情:
#include <iostream>
#include <errno.h>
#include <map>
namespace MyError
{
enum MyReturnCode: int
{
MY_INVALID_VAL = 0 , /* Invalid Mapping */
MY_ERROR_EPERM = -1104, /* Operation not permitted */
MY_ERROR_ENOENT = -1105, /* No such file or directory */
};
MyReturnCode fromErrno(int e)
{
static const std::map<int, MyReturnCode> mapping {
{ EPERM, MY_ERROR_EPERM},
{ ENOENT, MY_ERROR_ENOENT}
};
if(mapping.count(e))
return mapping.at(e);
else
return MY_INVALID_VAL;
}
}
int main()
{
std::cout << MyError::fromErrno(ENOENT) << std::endl;
std::cout << MyError::fromErrno(42) << std::endl;
return 0;
}