Assert.cxx
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "Assert.hxx"
00023 #include <iostream>
00024 #include <cstdlib>
00025 #include <csignal>
00026 #if defined(__linux__)
00027 #include <execinfo.h>
00028 #endif
00029
00030 #ifdef __GNUC__
00031 #include <cxxabi.h>
00032 #endif//__GNUC__
00033
00034
00035
00036 namespace CLAM {
00037
00038
00039 std::string demangleSymbol(const std::string & mangledName)
00040 {
00041 std::string result=mangledName;
00042 #ifdef __GNUC__
00043 size_t parenthesisPos = result.find_first_of('(');
00044 if (parenthesisPos == std::string::npos) return result;
00045 size_t endPos = result.find_first_of("+", parenthesisPos);
00046 if (endPos == std::string::npos) endPos = result.find_first_of(")", parenthesisPos);
00047 std::string head = result.substr(0,parenthesisPos+1);
00048 std::string tail = result.substr(endPos);
00049 std::string mangled = result.substr(parenthesisPos+1, endPos-parenthesisPos-1);
00050 int demangleError = 0;
00051 char * demangled = abi::__cxa_demangle(mangled.c_str(),0,0,&demangleError);
00052 if (!demangleError && demangled)
00053 result = head+demangled+tail;
00054 if (demangled) free(demangled);
00055 #endif//__GNUC__
00056 return result;
00057 }
00058
00059 void DumpBacktrace(std::ostream & os)
00060 {
00061 #if defined(__linux__)
00062
00063 void *bt_array[100];
00064 char **bt_strings;
00065 int num_entries;
00066
00067 if ((num_entries = backtrace(bt_array, 100)) < 0) {
00068 os << " Unable to generate a backtrace" << std::endl;
00069 return;
00070 }
00071
00072 if ((bt_strings = backtrace_symbols(bt_array, num_entries)) == NULL) {
00073 os << " Unable to adquire symbols names for the backtrace" << std::endl;
00074 return;
00075 }
00076
00077 os << "\n Backtrace:\n" << std::endl;
00078 for (int i = 0; i < num_entries; i++) {
00079 os << "[" << i << "] " << demangleSymbol(bt_strings[i]) << std::endl;
00080 }
00081 free(bt_strings);
00082 #else
00083 os << " Unable to adquire symbols names for the backtrace" << std::endl;
00084 #endif
00085 }
00086
00087
00088
00089
00090
00091 bool disabledCLAMAssertBreakpoint = false;
00092
00093
00094
00095 static void DefaultAssertHandler(const char* message, const char* filename, int lineNumber )
00096 {
00097 std::cerr << "##########################################################" << std::endl;
00098 std::cerr << "################### ASSERTION FAILED #####################" << std::endl;
00099 std::cerr << "##########################################################" << std::endl;
00100 std::cerr << "At file " << filename << " line " << lineNumber << std::endl;
00101 std::cerr << message << std::endl;
00102 DumpBacktrace(std::cerr);
00103 }
00104
00105 static AssertFailedHandlerType CurrentAssertFailedHandler=DefaultAssertHandler;
00106
00107 AssertFailedHandlerType SetAssertFailedHandler(AssertFailedHandlerType handler) {
00108 AssertFailedHandlerType oldHandler = CurrentAssertFailedHandler;
00109 CurrentAssertFailedHandler = handler;
00110 return oldHandler;
00111 }
00112
00113 void ExecuteAssertFailedHandler(const char* message, const char* filename, int lineNumber )
00114 {
00115 CurrentAssertFailedHandler(message,filename,lineNumber);
00116 }
00117
00118 bool ErrAssertionFailed::breakpointInCLAMAssertEnabled = true;
00119
00120 ErrAssertionFailed::ErrAssertionFailed(const char* message, const char* filename, int lineNumber)
00121 : Err(message)
00122 {
00123 if (!breakpointInCLAMAssertEnabled) return;
00124
00125 CurrentAssertFailedHandler( message, filename, lineNumber );
00126 }
00127
00128
00129
00130 static void DefaultWarningHandler(const char* message, const char* filename, int lineNumber )
00131 {
00132 std::cerr << "####### WARNING: At file " << filename << " line " << lineNumber << std::endl;
00133 std::cerr << "\033[31m" << message << "\033[0m" << std::endl;
00134 }
00135
00136 static WarningHandlerType CurrentWarningHandler=DefaultWarningHandler;
00137
00138 WarningHandlerType SetWarningHandler(WarningHandlerType handler) {
00139 WarningHandlerType oldHandler = CurrentWarningHandler;
00140 CurrentWarningHandler = handler;
00141 return oldHandler;
00142 }
00143
00144 void ExecuteWarningHandler(const char* message, const char* filename, int lineNumber )
00145 {
00146 CurrentWarningHandler(message,filename,lineNumber);
00147 }
00148
00149 #if 0 // defined(__linux__)
00150 class SystemSignalTrapper
00151 {
00152 int _signal;
00153 sighandler_t _oldHandler;
00154 public:
00155 SystemSignalTrapper(int signal, sighandler_t handler) :
00156 _signal(signal)
00157 {
00158 _oldHandler = std::signal(signal, handler);
00159 }
00160 ~SystemSignalTrapper()
00161 {
00162 std::signal(_signal, _oldHandler);
00163 }
00164 };
00165 void segvSignalHandler(int myInt)
00166 {
00167 std::cerr << std::endl;
00168 std::cerr << "##########################################################" << std::endl;
00169 std::cerr << "#################### BAD MEMORY ACCES ####################" << std::endl;
00170 std::cerr << "##########################################################" << std::endl;
00171 DumpBacktrace(std::cerr);
00172 std::abort();
00173 }
00174
00175 static SystemSignalTrapper segvSignalTrapper(SIGSEGV,segvSignalHandler);
00176 #endif //defined linux
00177
00178
00179 }
00180
00181