/* MyException.h*/
#ifndef EXCEPTION_TEST_H_
#define EXCEPTION_TEST_H_
#include <exception>
#include <string>
#define MY_THROW(ExClass,args...) \
do\
{\
ExClass e(args); \
e.Init(__FILE__,__PRETTY_FUNCTION__,__LINE__); \
throw e; \
}while(false)
#define MY_DEFINE_EXCEPTION(ExClass,Base) \
ExClass(const std::string& msg="") throw() \
:Base(msg) \
{} \
~ExClass() throw(){} \
std::string GetClassName() const \
{ \
return #ExClass; \
}
class ExceptionBase:public std::exception
{
public:
ExceptionBase(const std::string& msg="")throw();
virtual ~ExceptionBase() throw();
void Init(const char *file,const char* func,int line);
virtual std::string GetClassName() const;
virtual std::string GetMessage() const;
const char* what() const throw();
const std::string* ToString() const;
std::string GetStackTrace() const;
protected:
std::string mMsg;
const char* mFile;
const char* mFunc;
int mLine;
private:
enum{MAX_STACK_TRACE_SIZE=50};
void* mStackTrace[MAX_STACK_TRACE_SIZE];
size_t mStackTraceSize;
mutable std::string mWhat;
};
class ExceptionDerived:public ExceptionBase
{
public:
MY_DEFINE_EXCEPTION(ExceptionDerived,ExceptionBase);
};
#endif
/MyException.cpp /
#include <execinfo.h>
#include <stdlib.h>
#include <cxxabi.h>
#include <iostream>
#include <sstream>
#include "MyException.h"
using namespace std;
ExceptionBase::ExceptionBase(const string& msg) throw()
:mMsg(msg),
mFile("<unknow file>"),
mFunc("<unknow func>"),
mLine(-1),
mStackTraceSize(0)
{
}
ExceptionBase::~ExceptionBase() throw()
{}
void ExceptionBase::Init(const char* file,const char* func,int line)
{
mFile=file;
mFunc=func;
mLine=line;
m_StackTraceSize=backtrace(mStackTrace,MAX_STACK_TRACE_SIZE);
}
string ExceptionBase::GetClassName() const
{
return "ExceptionBase";
}
const char* ExceptionBase::what() const throw()
{
return ToString().c_str();
}
const string& ExceptionBase::ToString() cosnt
{
if(mWhat.empty())
{
stringstream sstr("");
if(mLine>0)
{
sstr<<mFile<<"("<<mLine<<")";
}
sstr<<":"<<GetClassName();
if(!GetMessage().empty())
{
sstr<<":"<<GetMessage();
}
sstr<<"\nStack Trace:\n";
sstr<<GetStackTrace();
mWhat=sstr.str();
}
return mWhat;
}
string ExceptionBase::GetMessage()const
{
return mMsg;
}
string ExceptionBase::GetStackTrace() cosnt
{
if(mStackTraceSize==0)
return "<No Stack Trace\n";
char** strings=backtrace_symbols(mStackTrace,10);
if(strings==NULL)
return "<Unknow error:backtrace_symbols returned null>\n";
string result;
for(size_t i=0;i<mStackTraceSize;++i)
{
string mangledName=strings[i];
string::size_type begin=mangledName.find('(');
string::size_type end=mangledName.find('+',begin);
if(begin==string::npos||end==string::npos)
{
result+=mangledName;
result+='\n';
continue;
}
++begin;
int status;
char* s=abi::__cxa_demangle(mangledName.substr(begin,end-begin).c_str(),NULL,0,&status);
if(status!=0)
{
result+=mangledName;
result+='\n';
continue;
}
string demangledName(s);
free(s);
result+=mangledName.substr(0,begin);
result+=demangledName;
result+=mangledName.substr(end);
result+='\n';
}
free(strings);
return result;
}
/test/
#include "MyException.h"
#include <iostream>
using namespace std;
int f2()
{
MY_THROW(ExceptionDerived,"f2 throw");
}
void f1()
{
try{
f2();
}
catch(ExceptionDerived& e)
{
cout<<e.what()<<endl;
}
}
int main()
{
f1();
}