异常
代码位置:base/Exception.h base/Exception.cc
其中noexcept表示当前函数不会产生异常,override表示当前函数是重写了父类的虚函数,异常处理是通过继承std的exception类实现的,其中重写了what和stackTrace函数
class Exception : public std::exception
{
public:
Exception(std::string what);
~Exception() noexcept override = default;
// default copy-ctor and operator= are okay.
const char* what() const noexcept override
{
return message_.c_str();
}
const char* stackTrace() const noexcept
{
return stack_.c_str();
}
private:
std::string message_;
std::string stack_;
};
其中最主要的功能是打印函数调用栈,该功能的实现主要借助了backtrace和backtrace_symbols两个系统函数
其中backtrace函数可以获取函数调用的栈帧的地址
而backtrace_symbol可以获取栈帧地址对应的函数名
string stackTrace(bool demangle)
{
string stack;
const int max_frames = 200;
void* frame[max_frames];
int nptrs = ::backtrace(frame, max_frames);
char** strings = ::backtrace_symbols(frame, nptrs);
if (strings)
{
size_t len = 256;
char* demangled = demangle ? static_cast<char*>(::malloc(len)) : nullptr;
for (int i = 1; i < nptrs; ++i) // skipping the 0-th, which is this function
{
if (demangle)
{
// https://panthema.net/2008/0901-stacktrace-demangled/
// bin/exception_test(_ZN3Bar4testEv+0x79) [0x401909]
char* left_par = nullptr;
char* plus = nullptr;
for (char* p = strings[i]; *p; ++p)
{
if (*p == '(')
left_par = p;
else if (*p == '+')
plus = p;
}
if (left_par && plus)
{
*plus = '\0';
int status = 0;
char* ret = abi::__cxa_demangle(left_par+1, demangled, &len, &status);
*plus = '+';
if (status == 0)
{
demangled = ret; // ret could be realloc()
stack.append(strings[i], left_par+1);
stack.append(demangled);
stack.append(plus);
stack.push_back('\n');
continue;
}
}
}
// Fallback to mangled names
stack.append(strings[i]);
stack.push_back('\n');
}
free(demangled);
free(strings);
}
return stack;
}