Exception类是为异常捕获而设计,可以获得异常的信息以及栈的回溯信息
(原来的代码没有demangle成员函数,输出的格式比较难看,加了demangle成员函数,利用demangle成员函数可以转换格式,使得输出的格式更加接近我们的习惯)
以下的代码是加入了demangle成员函数后的:
Exception.h

// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
//
// Author: Shuo Chen (chenshuo at chenshuo dot com)

#ifndef MUDUO_BASE_EXCEPTION_H
#define MUDUO_BASE_EXCEPTION_H

#include <muduo/base/Types.h>
#include <exception>

namespace muduo
{

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_;//保存栈回溯信息的字符串
};

}

#endif  // MUDUO_BASE_EXCEPTION_H

Exception.cc

// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
//
// Author: Shuo Chen (chenshuo at chenshuo dot com)

#include <muduo/base/Exception.h>

#include <cxxabi.h>
#include <execinfo.h>
#include <stdlib.h>
#include <stdio.h>

using namespace muduo;

Exception::Exception(const char* msg)  : message_(msg)
{
  fillStackTrace();//构造函数直接调用 fillStackTrace
}

Exception::Exception(const string& msg) : message_(msg)
{
  fillStackTrace();
}

Exception::~Exception() throw ()
{
}

const char* Exception::what() const throw()
{
  return message_.c_str();
}

const char* Exception::stackTrace() const throw()
{
  return stack_.c_str();
}

void Exception::fillStackTrace()
{
  const int len = 200;
  void* buffer[len];//保存200个地址,是一个数组的指针
  //栈回溯,保存各个栈帧的地址
  //buffer中的每一个项都是void*,用于保存函数的地址
  int nptrs = ::backtrace(buffer, len);//nptr为实际保存的个数
  //根据地址,转成相应的函数符号
  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_字符串
      stack_.append(demangle(strings[i]));//转化后在存入
      stack_.push_back('\n');
    }
    free(strings);//存放的地址使用malloc开辟出来的,需要我们自己释放
  }
}
//该函数实现栈回溯信息的格式转换
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;
}

以下是一个简单的测试函数:

//Exception类测试函数
#include <muduo/base/Exception.h>
#include <stdio.h>
//定义Bar类
class Bar
{
 public:
  void test()
  {
    throw muduo::Exception("oops");//抛出异常
  }
};
void foo()
{
  Bar b;
  b.test();
}
int main()
{
  try
  {
    foo();//可能发生异常
  }
  catch (const muduo::Exception& ex)//捕获异常
  {
    printf("reason: %s\n", ex.what());//抛出异常信息
    printf("stack trace: %s\n", ex.stackTrace());//把异常栈回溯信息抛出,即在哪里抛出异常,打印函数的调用栈
  }
}

单独编译后运行结果如下:(没有使用demangle成员函数)
这里写图片描述
使用demangle成员函数:
这里写图片描述

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐