2023年11月29日发(作者:)

boostsystem

跨平台、可移植⼀直是很多C++程序员追求的⽬标。但由于C++是⼀种中级语⾔,很多时候都要和操作系统打交道,因⽽功能代码常常和平台结合

很紧密,难以做到真正的跨平台,再向其他平台移植代码的时候修改操作系统相关的代码通常是必不可少的⼯作

boost库提供了数个操作系统相关的库,部分的屏蔽了操作系统的底层细节,能够提⾼程序的可移植性。⽐如说system库,它封装了操作系统底层

的错误代码,为上层提供了⼀个可移植的统⼀的处理接⼝

概述

C++中处理错误的最佳⽅式是使⽤异常,但操作系统和很多底层API不具有这个能⼒,它们⼀般使⽤更通⽤也更难操作的错误码来表⽰

出错的原因,不同的操作系统的错误码通常是不兼容的,这给跨平台的程序带来了很⼤的⿇烦

system库使⽤轻量级的对象封装了操作系统底层的错误码和错误信息,使调⽤操作系统功能的程序可以很容易的被移植到其他操作系

统。它作为基础部件被chrone、filesystem、asio等库使⽤,并且被接受为C++标准(C++11.19.5)

system库需要编译才能使⽤,在jamfile⾥指定lib的语句是:

lib boost_system

system库也提供⼀个特别的宏,可以把system库完全头⽂件话,不需要编译或者链接

BOOST_ERROR_CODE_HEADER_ONLY

system库位于名字空间,需要包含头⽂件(注意与C++标准名字不同)。

boost::system

即:

#define BOOST_ERROR_CODE_HEADER_ONLY // system

⽆需编译就可以使⽤

#include

using namespace boost:system;

错误码

system库在名字空间下定义了⼀个很⼤的枚举类,它定义了通⽤的可移植的错误码,我们应该尽量使⽤它来

boost::system::errcerrc_t

标记错误原因:

namespace errc{ //boost::system::errc

enum errc_t{ //C++enum class

标准定义为

success = 0;

address_family_not_support;

address_in_use;

address_not_available;

already_connect;

...

};

};

system库还在头⽂件⾥分别定义了Linux和windows操作系统的特定

的错误值枚举,分别位于名字空间。如果针对这两个操作系统做特定编程,则可

boost::system::linux_errorboost::system::windows_error

以包含这两个头⽂件

错误类别

system库的核⼼类是error_category、error_code和error_condition.

error_category

是⼀个抽象基类,⽤于标识错误码的类别,它的类摘要如下:

class error_category : public noncopyable

{

public:

virtual ~error_category(){}

virtual const char * name() const = 0;

virtual std::string message( int ev ) const = 0;

virtual error_condition default_error_condition( int ev ) const;

virtual bool equivalent( int code,

const error_condition & condition ) const;

virtual bool equivalent( const error_code & code,

int condition ) const;

bool operator==(const error_category & rhs) const { return this == &rhs; }

bool operator!=(const error_category & rhs) const { return this != &rhs; }

bool operator<( const error_category & rhs ) const

{

return std::less<const error_category*>()( this, &rhs );

}

};

error_category 的核⼼函数共有四个

成员函数可以获得类别的名称

name()

message()

可以获得错误码ev对应的描述信息

defautl_error_condition()

是⼀个⼯程⽅法,它由错误码ev产⽣⼀个error_condition对象

equivalent()

⽤于⽐较两个错误码是否相等。

error_category 不能直接使⽤,必须使⽤继承的⽅式⽣成它的⼦类。system库在匿名名字空间⾥预定义了两个⼦

,⽤于表⽰系统错误和通⽤可移植错误,可以⽤位于名字空间的⾃由函

system_error_categorygeneric_error_categoryboost::system

间接访问。

system_category()generic_category()

如果我们需要建⽴⼀个新的错误类别,则可以从error_category派⽣⼀个新类。新类中只有name()和message()是必须实现的,因为他们

是纯虚函数,其余的函数可以使⽤error_category的默认实现。

⽐如,我们可以定义⼀个新的错误类别my_category的代码如下:

class my_category : public error_category

{

public:

virtual const char *name() const

{ return "myapp_category"; }

virtual string message(int ev)const

{

string msg;

switch(ev)

{

case 0:

msg = "ok";break;

default:

msg = "some error";break;

}

return msg;

}

};

错误码

error_codeerror_condition

都⽤于表⽰错误码:

但error_code更接近操作系统和底层API,⽽error_condition则更偏重于可移植。

两者的声明很类似,但error_code多了⼀个default_error_condition()⽅法,可以把error_code转换成error_condition。

error_code的类摘要如下:

class error_code{

public:

error_code();

error_code(int val, const error_category & cat);

void assign(int val, const error_category & cat); //

赋值

void clear(); //

消除错误码

int value() const; //

获取错误码

const error_category& category() const; //

获取错误类别

error_condition default_error_condition() const; //error_condition

转换为

string message() const; //

获取错误描述信息

explicit operator bool() const;

bool operator==(const error_code& lhs, const error_code& rhs);

bool operator!=(const error_code& lhs, const error_code& rhs);

bool operator<(const error_code& lhs, const error_code& rhs);

};

error_code和error_condition都可以从⼀个整数错误值或者errc_t枚举构造,并同时指定所属的错误类别。如果⽆参构造,那么错误值会

是0(⽆错误)。

error_code对象内部的值可以⽤value()获得,获得错误描述要使⽤message(),它将调⽤error_category的message()返回描述信息。函

数category()可以返回错误码所属的类别,因此message()相当于:

ec.category().message(ec.value());

不同的错误类别决定了error_code的含义,相同的代码如果属于不同的类别,那么将具有不同的含义:

my_category my_cat;

error_code ec(10, my_cat);

cout << ec.value() << ec.message() << endl;

ec = error_code(10, system_category());

cout << ec.value() << ec.message() << endl;

这段代码的运⾏结果是:

10 some_error

10 NO child processes

进⼀步⽰范这两个错误代码类的⽤法如下:

cout << system_category().name() << endl; //

输出类别名称

error_code ec; //

默认构造⼀个错误码对象

assert(ec.value() == errc::success); //

默认⽆错误

assert(!ec); // bool

默认⽆错误,可以转换

assert(ec.category() == system_category());

ec.assign(3L, system_category()); // 3

错误值为

auto econd = ec.default_error_condition(); //

产⽣⼀个可移植的错误码

assert(econd == ec); //

⽐较

//system_category

也可以直接⽤产⽣可移植的错误码

assert(econd == system_category().default_error_condition(3L));

cout << ec.message() << endl; //

输出错误描述信息

cout << econd.message() << endl;

cout << econd.value() << endl; //

输出可移植的错误码

有时候相同的错误码error_code和error_condition可能错误信息并不相同,在编写跨平台的程序时应该尽量使⽤error_condition,并且

使⽤不依赖于具体错误值的errorc_t枚举

错误异常

system库还提供⼀个异常类,它是的⼦类,是对error_code的⼀个适配,可以把error_code应⽤到C++的

system_errorstd::runtime_error

异常处理机制中。

system_error位于名字空间,使⽤时需要另外包含头⽂件,即:

boost::system

#include

using namespace boost::system

它的类摘要如下:

class system_error : public std::runtime_error

{

public:

system_error( error_code ec );

system_error( error_code ec, const std::string & what_arg );

system_error( error_code ec, const char* what_arg );

system_error( int ev, const error_category & ecat );

system_error( int ev, const error_category & ecat,

const std::string & what_arg );

system_error( int ev, const error_category & ecat,

const char * what_arg );

virtual ~system_error() throw() {}

const error_code & code() const throw();

const char * what() const throw();

};

system_error 和标准⽤法没有太多的差别,构造时需要传⼊error_code对象,新增的成员函数code()可以返回这个error_code对象的引

⽤。

⽰例:

try

{

throw system_error(error_code(5, system_category()));

}

catch (system_error& e)

{

cout << e.what();

}