菜鸟笔记
提升您的技术认知

C++的异常处理和堆栈信息

c++标准异常

#include <exception>
// std::exception

堆栈信息

获取堆栈信息,主要是使用execinfo.h中定义的几个函数.

在抛出异常之后,通过execinfo.h中定义的函数,获取堆栈信息,有助于定位问题.

/* Copyright (C) 1998-2016 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, see
   <http://www.gnu.org/licenses/>.  */

#ifndef _EXECINFO_H
#define _EXECINFO_H 1

#include <features.h>

__BEGIN_DECLS

/* Store up to SIZE return address of the current program state in
   ARRAY and return the exact number of values stored.  */
extern int backtrace (void **__array, int __size) __nonnull ((1));


/* Return names of functions from the backtrace list in ARRAY in a newly
   malloc()ed memory block.  */
extern char **backtrace_symbols (void *const *__array, int __size)
     __THROW __nonnull ((1));


/* This function is similar to backtrace_symbols() but it writes the result
   immediately to a file.  */
extern void backtrace_symbols_fd (void *const *__array, int __size, int __fd)
     __THROW __nonnull ((1));

__END_DECLS

#endif /* execinfo.h  */

自定义异常类

BacktraceException.h

/*
 * BacktraceException.h
 *
 *  Created on: 2018-6-10
 */

#ifndef BACKTRACEEXCEPTION_H_
#define BACKTRACEEXCEPTION_H_

#include <exception>
#include <string>

class BacktraceException : public std::exception
{
public:
    BacktraceException(const std::string& msg);
    virtual ~BacktraceException()throw();
    const char* what()const throw()override;
    const char* stackTrace()const throw();
private:
    void fillStackTace();
private:
    std::string msg_;
    std::string stack_;
};

#endif /* BACKTRACEEXCEPTION_H_ */

BacktraceException.cpp

/*
 * BacktraceException.cpp
 *
 *  Created on: 2018-6-10
 *      Author:
 */

#include <execinfo.h>
#include <stdlib.h>
#include "BacktraceException.h"

BacktraceException::BacktraceException(const std::string& msg):msg_(msg) {
    fillStackTace();
}

BacktraceException::~BacktraceException() throw() {
    // TODO Auto-generated destructor stub
}

const char* BacktraceException::what()const throw(){
    return msg_.c_str();
}

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

void BacktraceException::fillStackTace(){
      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)
        {
          stack_.append(strings[i]);
          stack_.push_back('\n');
        }
        free(strings);
      }
}

测试

#include "BacktraceException.h"

#ifdef TEST_BACKTRACE_EXCEPTION
#include <iostream>
int main()
{
    try{
        throw BacktraceException("this is an BacktraceException");
    }catch(BacktraceException &e){
        std::cout<<e.what()<<std::endl;
        std::cout<<e.stackTrace()<<std::endl;
    }
}

#endif // TEST_BACKTRACE_EXCEPTION