《Hands-On System Programming with C++》读书笔记之十三
本章介绍三种Linux系统开发中的异常处理的方法:
- POSIX风格
- C风格
- C++风格
POSIX风格的错误处理
POSIX风格错误处理提供最基本的错误处理,通用性最高。
一般地,函数成功时返回0,失败时返回-1并把错误代码存入全局宏定义errno。
#include <cstring>
#include <iostream>
int myfunc(int val)
{
if (val == 42)
{
errno = EINVAL;
return -1;
}
return 0;
}
int main()
{
if (myfunc(1) == 0)
{
std::cout << "success\n"; // success
}
else
{
std::cout << "failure: " << strerror(errno) << '\n';
}
if (myfunc(42) == 0)
{
std::cout << "success\n";
}
else
{
std::cout << "failure: " << strerror(errno) << '\n';
// failure: Invalid argument
}
}
上面的例子用到了*strerror()*函数,它可以把POSIX错误代码转换成可读的字符串。
当希望既需要返回值,又返回错误代码时,可以使用std::pair模板。
#include <cstring>
#include <iostream>
#include <utility>
std::pair<int, bool> myfunc(int val)
{
if (val == 42)
{
errno = EINVAL;
return {
0, false};
}
return {
42,true};
}
int main()
{
if (auto [handle, success] = myfunc(1); success)
{
std::cout << "success: " << handle << '\n'; // success: 42
}
else
{
std::cout << "failure: " << strerror(errno) << '\n';
}
if (auto [handle, success] = myfunc(42); success)
{
std::cout << "success: " << handle << '\n';
}
else
{
std::cout << "failure: " << strerror(errno) << '\n';
// failure: Invalid argument
}
}
由于系统编程中出现很多嵌套的调用,如果每次返回都按照这种POSIX风格进行分支判断,每层都会传递错误信息而且代码十分臃肿。
但是由于这种方法的层次清除,它是符合RAII原则的。
认识set jump exception
Set jump也被是为C风格的异常。它允许开发者设置一个当异常发生时的返回位置。它是不符合RAII原则的。
#include <cstring>
#include <csetjmp>
#include <iostream>
std::jmp_buf jb;
void myfunc(int val)
{
if (val == 42)
{
errno = EINVAL;
std::longjmp(jb, -42);
}
}
int main()
{
if (setjmp(jb) == -42)
{
std::cout &