stack traces with any exception class
Define THROW_EXCEPTION(E) which takes an exception class instance, and uses it to construct an instance of a class which is a subclass of E and ExceptionMixin. The original instance is discarded, and the newly constructed sub-class is thrown. Equivalent to "throw E;". Define THROW_EXCEPTION2(ETYPE,MSG) which takes an exception class type, and argument. Directly constructs a ExceptionMixin sub-class with the given message argument. Equivalent to "throw ETYPE(MSG);". Define PRINT_EXCEPTION2(E, FP) If E is a instance of a sub-class of ExceptionMixin then write information to FP (FILE*). Define SHOW_EXCEPTION(E) If E is a instance of a sub-class of ExceptionMixin then return a std::string with information.
This commit is contained in:
87
pvDataApp/misc/epicsException.cpp
Normal file
87
pvDataApp/misc/epicsException.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvDataCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
|
||||
#include "epicsException.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
namespace epics{namespace pvData{
|
||||
|
||||
void
|
||||
ExceptionMixin::print(FILE *fp) const
|
||||
{
|
||||
fprintf(fp, "On line %d of %s\n",m_line,m_file);
|
||||
|
||||
#if defined(EXCEPT_USE_BACKTRACE)
|
||||
if(m_depth>0) {
|
||||
fflush(fp); // must flush before using raw handle
|
||||
backtrace_symbols_fd(m_stack, m_depth, fileno(fp));
|
||||
fprintf(fp, "To translate run 'addr2line -e execname 0xXXXXXXX ...'\n"
|
||||
" Note: Must be compiled with debug symbols\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string
|
||||
ExceptionMixin::show() const
|
||||
{
|
||||
std::ostringstream out;
|
||||
|
||||
out<<"On line "<<m_line<<" of "<<m_file<<"\n";
|
||||
|
||||
#if defined(EXCEPT_USE_BACKTRACE)
|
||||
if (m_depth>0) {
|
||||
|
||||
char **symbols=backtrace_symbols(m_stack, m_depth);
|
||||
|
||||
for(int i=0; i<m_depth; i++) {
|
||||
out<<symbols[i]<<"\n";
|
||||
}
|
||||
|
||||
free(symbols);
|
||||
}
|
||||
|
||||
#endif
|
||||
return out.str();
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
BaseException::what() const throw()
|
||||
{
|
||||
try{
|
||||
if (base_msg.size()==0) {
|
||||
const char *base=std::logic_error::what();
|
||||
std::string out, stack;
|
||||
|
||||
const ExceptionMixin *info=dynamic_cast<const ExceptionMixin*>(this);
|
||||
if(info) {
|
||||
stack=info->show();
|
||||
}
|
||||
|
||||
out.reserve(strlen(base)+1+stack.size()+1);
|
||||
|
||||
out+=base;
|
||||
out+="\n";
|
||||
if(info) {
|
||||
out+=stack;
|
||||
out+="\n";
|
||||
}
|
||||
|
||||
base_msg.swap(out);
|
||||
}
|
||||
return base_msg.c_str();
|
||||
} catch(std::bad_alloc&) {
|
||||
return "BaseException::what - Insufficient memory to construct message";
|
||||
} catch(...) {
|
||||
return "BaseException::what - Unknown error when constructing message";
|
||||
}
|
||||
}
|
||||
|
||||
}}
|
||||
Reference in New Issue
Block a user