muduo学习异常类

头文件
#include <execinfo.h>


获取程序的堆栈信息的函数
/* Store up to SIZE return address of the current program state in
   ARRAY and return the exact number of values stored.  */
int backtrace(void **array, int size);


/* Return names of functions from the backtrace list in ARRAY in a newly
   malloc()ed memory block. 我们必须手动释放该空间 */
char **backtrace_symbols(void *const *array, int size);


/* This function is similar to backtrace_symbols() but it writes the result
   immediately to a file.  */
void backtrace_symbols_fd(void *const *array, int size, int fd);


注意点:
1.backtrace的实现依赖于栈指针(fp寄存器), 在gcc编译过程中任何非零的优化等级(-On参数)
或者加入了栈指针优化参数-fomit-frame-pointer后多将不能正确得到程序栈信息;
2.backtrace_symbols的实现需要符号名称的支持,在gcc编译过程中需要加入-rdynamic参数;
3.内联函数没有栈帧,它在编译过程中被展开在调用的位置;
4.尾调用优化(Tail-call Optimization)将复用当前函数栈,而不再生成新的函数栈,这将导致栈信息不能正确被获取。


void print_stack_info()  
{  
    int j, nptrs;  
    void *buffer[BACKTRACE_SIZE];  
    char **strings;  
      
    nptrs = backtrace(buffer, BACKTRACE_SIZE);     
    printf("backtrace() returned %d addresses\n", nptrs);  
  
    strings = backtrace_symbols(buffer, nptrs);  
    if (strings == NULL) 
    {  
        perror("backtrace_symbols");  
        exit(EXIT_FAILURE);  
    }  
  
    for (j = 0; j < nptrs; j++)  
        printf("%s\n",strings[j]);  
  
    free(strings);  
}  


相比C语言,C++支持函数重载、类、模版等各种特性,如果C++的符号修饰仍按照C那样直接使用对应名称,虽然可读性很好,却不可避免的会出现各种错乱
于是C++符号修饰别名(mangled name)被设计出来,用来解决上述问题,然而修饰规则取决于编译器实现,没有统一标准,比如gcc、msvc就各有一套,但好在
都提供了相应接口进行解析(demangle),这里有个网站http://demangler.com/可以在线解析
头文件 #include <cxxabi.h>
GNU  char *name = abi::__cxa_demangle(MANGLED_NAME, NULL, NULL, &status);

利用该特性对函数异常类的封装


virtual 虚析构函数是为了多态时释放子类的资源
virtual what() 实现多态的效果 std::Exception中存在what()的虚函数
throw()表示该函数能抛除所有的类型的异常


class Exception:public std::Exception
{
public:
explict Exception(const char* msg);
explict Exception(const string& msg);
virtual ~Exception() throw();
virtual const char* what() const throw();
const char* stackTrace() const throw();
private:
void fillStackTrace();
void demangle();
string err_message;
string stack_info;
};


Exception::Exception(const char* msg): err_message(msg)
{
  fillStackTrace();
}


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


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


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


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


ssacnf 的格式化输入
1、 * 亦可用于格式中, (即 %*d 和 %*s) 加了星号 (*) 表示跳过此数据不读入. (也就是不把此数据读入参数中) 
2、{a|b|c}表示a,b,c中选一,[d],表示可以有d也可以没有d。 
3、width表示读取宽度。 
4、{h | l | I64 | L}:参数的size,通常h表示单字节size,I表示2字节 size,L表示4字节size(double例外),l64表示8字节size。
5、type :这就很多了,就是%s,%d之类。 
6、特别的:%*[width] [{h | l | I64 | L}]type 表示满足该条件的被过滤掉,不会向目标参数中写入值


%[a-z] 表示匹配a到z中任意字符,贪婪性(尽可能多的匹配)
%[aB'] 匹配a、B、'中一员,贪婪性
%[^a] 匹配非a的任意字符,贪婪性


//函数修饰名--->函数名
string Exception::demangle(const char *mangle_name)
{
size_t size;
int status;
char temp[120];

if(1 == sscanf(mangle_name, "%*[^(]%*[^_]%127[^)+]", temp))
{
if(NULL != (demangled = abi::cxa_demangle(temp, NULL, &size, &status)))
{
string result(demangled);
free(demangled);
retutn result;
}
}

if(1 == sscanf(mangle_name, "%127s", temp))
return temp;

return mangle_name;
}


void Exception::fillStackTrace()
{
  const int len = 200;
  void* buffer[len];
  //该函数用与获取当前线程的调用堆栈
  int nptrs = ::backtrace(buffer, len);
  //backtrace_symbols将从backtrace函数获取的信息转化为一个字符串数组
  char** strings = ::backtrace_symbols(buffer, nptrs);
  if (strings)
  {
    for (int i = 0; i < nptrs; ++i)
    {
      stack_.append(demangle(strings[i]));
      stack_.push_back('\n');
    }
    free(strings);
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值