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成员函数:

muduo网络库源码学习————Exception类的更多相关文章

  1. muduo网络库源码学习————线程类

    muduo库里面的线程类是使用基于对象的编程思想,源码目录为muduo/base,如下所示: 线程类头文件: // Use of this source code is governed by a B ...

  2. muduo网络库源码学习————日志类封装

    muduo库里面的日志使方法如下 这里定义了一个宏 #define LOG_INFO if (muduo::Logger::logLevel() <= muduo::Logger::INFO) ...

  3. muduo网络库源码学习————Timestamp.cc

    今天开始学习陈硕先生的muduo网络库,moduo网络库得到很多好评,陈硕先生自己也说核心代码不超过5000行,所以我觉得有必要拿过来好好学习下,学习的时候在源码上面添加一些自己的注释,方便日后理解, ...

  4. muduo网络库源码学习————线程池实现

    muduo库里面的线程池是固定线程池,即创建的线程池里面的线程个数是一定的,不是动态的.线程池里面一般要包含线程队列还有任务队列,外部程序将任务存放到线程池的任务队列中,线程池中的线程队列执行任务,也 ...

  5. muduo网络库源码学习————互斥锁

    muduo源码的互斥锁源码位于muduo/base,Mutex.h,进行了两个类的封装,在实际的使用中更常使用MutexLockGuard类,因为该类可以在析构函数中自动解锁,避免了某些情况忘记解锁. ...

  6. muduo网络库源码学习————线程本地单例类封装

    muduo库中线程本地单例类封装代码是ThreadLocalSingleton.h 如下所示: //线程本地单例类封装 // Use of this source code is governed b ...

  7. muduo网络库源码学习————日志滚动

    muduo库里面的实现日志滚动有两种条件,一种是日志文件大小达到预设值,另一种是时间到达超过当天.滚动日志类的文件是LogFile.cc ,LogFile.h 代码如下: LogFile.cc #in ...

  8. muduo网络库源码学习————线程特定数据

    muduo库线程特定数据源码文件为ThreadLocal.h //线程本地存储 // Use of this source code is governed by a BSD-style licens ...

  9. muduo网络库源码学习————无界队列和有界队列

    muduo库里实现了两个队列模板类:无界队列为BlockingQueue.h,有界队列为BoundedBlockingQueue.h,两个测试程序实现了生产者和消费者模型.(这里以无界队列为例,有界队 ...

随机推荐

  1. intelij idea 和 eclipse 使用上的区别

    一.项目创建区别 使用基于IntelliJ的IDE,都会对project和module的关系比较糊涂.用简单的一句话来概括是: IntelliJ系中的Project相当于Eclipse系中的works ...

  2. Docker 清理命令 删除所有的镜像和容器

    杀死所有正在运行的容器 docker kill $(docker ps -a -q) 删除所有已经停止的容器 docker rm $(docker ps -a -q) 删除所有未打 dangling ...

  3. split(resource,limit) 中limit 的含义

    limit 参数控制模式应用的次数,因此影响结果数组的长度.如果该限制 n 大于 0,则模式将被最多应用 n - 1 次,数组的长度将不会大于 n,而且数组的最后项将包含超出最后匹配的定界符的所有输入 ...

  4. 【转】Centos7启动网卡(获取ip地址)

    这里之所以是查看下IP ,是我们后面要建一个Centos远程工具Xshell 连接Centos的时候,需要IP地址,所以我们这里先 学会查看虚拟机里的Centos7的IP地址 首先我们登录操作系统 用 ...

  5. 用threejs实现三维全景图

    网络上看到了3D全景图,发现threejs里面有一个库竟然可以实现,一下我贴出代码: <!DOCTYPE html> <html> <head> <meta ...

  6. stand up meeting 12-4

    今日进步: 1.国庆答题界面和结果界面的连接完成,并能显示GetRankData API返回结果和错误题目的单词信息. 2.天赋: 完成了整个  单词挑战需要碰到的"Storage" ...

  7. E - Max Sum Plus Plus Plus HDU - 1244 (线性区间DP)

    题目大意:  值得注意的一点是题目要求的是这些子段之间的最大整数和.注意和Max Sum Plus Plus这个题目的区别. 题解: 线性区间DP,对每一段考虑取或者不取.定义状态dp[i][j]指的 ...

  8. F. 蚂蚁装修

    单点时限: 2.0 sec 内存限制: 512 MB 还有一个月就开学了,爱学习的小蚂蚁想庆祝一下!于是它要把它的“家”装修一下.首先要做的就是贴地板.小蚂蚁“家”的地面可以看成一个2∗N 的方格 , ...

  9. linux 批量删除文件

    来源;https://www.cnblogs.com/sinpo/p/7106998.html linux下批量删除文件   1. 在linux批量删除多级目录下同一格式的文件,可采用find + e ...

  10. MarkDown排版测试

    1.标题设置 标题(大标题) 标题(小标题) 标题(一级标题) 标题( 二级标题) 标题(三级标题) 标题(四级标题) 备注:大标题与一级标题一样,小标题与二级标题一样,"#"前无 ...