muduo网络库源码复现笔记(三):base库的Exception.h

Muduo网络库简介

muduo 是一个基于 Reactor 模式的现代 C++ 网络库,作者陈硕。它采用非阻塞 IO 模型,基于事件驱动和回调,原生支持多核多线程,适合编写 Linux 服务端多线程网络应用程序。
muduo网络库的核心代码只有数千行,在网络编程技术学习的进阶阶段,muduo是一个非常值得学习的开源库。目前我也是刚刚开始学习这个网络库的源码,希望将这个学习过程记录下来。这个网络库的源码已经发布在GitHub上,可以点击这里阅读。目前Github上这份源码已经被作者用c++11重写,我学习的版本是没有使用c++11版本的。不过二者大同小异,核心思想是没有变化的。点这里可以看我的源代码,如果你对我之前的博客有兴趣,可以点击下面的连接:
muduo网络库源码复现笔记(一):base库的Timestamp.h
muduo网络库源码复现笔记(二):base库的Atomic.h

Exception.h

Exception类很简单,是对异常事件的封装。来开看一下它的类代码。

class Exception : public std::exception
{
 public:
  explicit Exception(const char* what);
  explicit Exception(const string& what);
  virtual ~Exception() throw();
  virtual const char* what() const throw();
  const char* stackTrace() const throw();

 private:
  void fillStackTrace();  //打印出栈帧信息
  string demangle(const char* symbol);//对栈帧信息进行翻译
  string message_; //储存异常信息
  string stack_;//异常时的栈信息
};

这里面值得关注的函数是两个私有成员函数fillStackTrace()和demangle()函数。下面分析一下。

fillStack()函数

fillStack函数的作用是获取目前线程的栈帧信息,然后转换成可读性较强的内容打印出来。看一下代码:

void Exception::fillStackTrace()
{
  const int len = 200;
  void* buffer[len];
  int nptrs = ::backtrace(buffer, len);
  char** strings = ::backtrace_symbols(buffer, nptrs);
  if (strings)
  {
    for (int i = 0; i < nptrs; ++i)
    {
      // TODO demangle funcion name with abi::__cxa_demangle
      //stack_.append(strings[i]);
	  stack_.append(demangle(strings[i]));
      stack_.push_back('\n');
    }
    free(strings);
  }
}

在fillStackTrace()中,我们首先定义一个泛型的指针数组buffer,buffer可以存储相关的栈帧信息。接着使用backtrace函数获取当前线程的栈帧信息。backtrace函数的原型如下:

int backtrace(void **buffer, int size);

size参数是指定buffer中可以存储的信息数目。返回值是实际返回的信息个数。
然后使用backtrace_symbols来将buffer中的信息转化为一个字符串数组,函数原型是

char **backtrace_symbols(void *const *buffer, int size);

但是backtrace_symbols函数返回的信息可读性不是很好,因为编译器会对定义的函数赋予一个新的名字,我们需要将这个新的名字翻译成可读的名字。这个功能由demangle函数完成。

demangle函数

demangle函数的功能如前所述,是将strings里的字符串信息翻译成可读性较好的信息。代码为:

string Exception::demangle(const char* symbol)
{
  size_t size;
  int status;
  char temp[128];
  char* demangled;
  //first, try to demangle a c++ name
  if (1 == sscanf(symbol, "%*[^(]%*[^_]%127[^)+]", temp)) {
    if (NULL != (demangled = abi::__cxa_demangle(temp, NULL, &size, &status))) {
      string result(demangled);
      free(demangled);
      return result;
    }
  }
  //if that didn't work, try to get a regular c symbol
  if (1 == sscanf(symbol, "%127s", temp)) {
    return temp;
  }
 
  //if all else fails, just return the symbol
  return symbol;
}

核心的工作,即将原始信息转换成可读性较强的信息,由__cxa_demangle完成。函数原型:

char *__cxa_demangle (const char *mangled_name, char *output_buffer, size_t *length, int *status);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值