1 Exception类
Exception类包括两个文件 :Exception.cc, Exception.h。
1.1 Exception.h
#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 message_;
string stack_;
};
}
1.2 Exception.cc
#include <muduo/base/Exception.h>
//#include <cxxabi.h>
#include <execinfo.h>
#include <stdlib.h>
using namespace muduo;
Exception::Exception(const char* msg)
: message_(msg)
{
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];
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_.push_back('\n');
}
free(strings);
}
}
2 backtrace函数
int backtrace(void **buffer, int size); 栈回溯,保存各个栈帧的地址;
buffer这个指针指向了一个数组,数组中的每一项都是void *类型,用来保存函数的地址。
3 backtrace_symbols函数
char **backtrace_symbols(void const buffer, int size);根据地址,转成相应的函数符号;
char strings = ::backtrace_symbols(buffer, nptrs);返回的是指针的指针;
4 还原C++函数的真实的名称
需要的头文件是<cxxabi.h>和<stdio.h>
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;
}
修改fillStackTrace()
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(demangle(strings[i]));
stack_.push_back('\n');
}
free(strings);
}
}