Changes in src/Helpers/Assert.cpp [112b09:506d2f]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Helpers/Assert.cpp
r112b09 r506d2f 5 5 * Author: crueger 6 6 */ 7 8 #include "Helpers/MemDebug.hpp"9 7 10 8 #include "Helpers/Assert.hpp" … … 46 44 } 47 45 48 using namespace Assert;49 50 46 #ifndef NDEBUG 51 47 52 Action _my_assert::defaultAction = Ask; 53 std::vector<Assert::hook_t> _my_assert::hooks; 48 #ifdef __GNUC__ 49 #include <cstdlib> 50 #include <execinfo.h> 51 #include <cxxabi.h> 52 #endif 54 53 55 std::map<std::string,bool> _wrapper::ignores; 56 const char* _wrapper::message_ptr = "source pointer did not point to object of desired type"; 57 const char* _wrapper::message_ref = "source reference did not contain object of desired type"; 54 Assert::Action Assert::_my_assert::defaultAction = Ask; 55 std::vector<Assert::hook_t> Assert::_my_assert::hooks; 58 56 57 std::map<std::string,bool> Assert::_wrapper::ignores; 58 const char* Assert::_wrapper::message_ptr = "source pointer did not point to object of desired type"; 59 const char* Assert::_wrapper::message_ref = "source reference did not contain object of desired type"; 59 60 60 bool _my_assert::check(const bool res, 61 const char* condition, 62 const char* message, 63 const char* filename, 64 const int line, 65 bool& ignore) 61 bool Assert::_my_assert::check(const char* condition, 62 const char* message, 63 const char* filename, 64 const int line, 65 bool& ignore) 66 66 { 67 if(!res){ 68 cout << "Assertion \"" << condition << "\" failed in file " << filename << " at line " << line << endl; 69 cout << "Assertion Message: " << message << std::endl; 70 while(true){ 71 char choice; 72 if(defaultAction==Ask) { 73 cout << "Please choose: (a)bort, (t)hrow execption, (i)gnore, al(w)ays ignore" << endl; 74 cin >> choice; 75 } 76 else{ 77 choice = ActionKeys[defaultAction]; 78 } 79 switch(choice){ 80 case 'a': 81 return true; 82 break; 83 case 't': 84 throw AssertionFailure(condition,filename,line,message); 85 break; 86 case 'w': 87 ignore = true; 88 // fallthrough 89 case 'i': 90 return false; 91 break; 92 } 67 cout << "Assertion \"" << condition << "\" failed in file " << filename << " at line " << line << endl; 68 cout << "Assertion Message: " << message << std::endl; 69 while(true){ 70 char choice; 71 if(defaultAction==Assert::Ask) { 72 #ifdef __GNUC__ 73 cout << "Please choose: (a)bort, (t)hrow execption, show (b)actrace, (i)gnore, al(w)ays ignore" << endl; 74 #else 75 cout << "Please choose: (a)bort, (t)hrow execption, (i)gnore, al(w)ays ignore" << endl; 76 #endif /* __GNUC__ */ 77 cin >> choice; 78 } 79 else{ 80 choice = ActionKeys[defaultAction]; 81 } 82 switch(choice){ 83 case 'a': 84 return true; 85 break; 86 case 't': 87 throw AssertionFailure(condition,filename,line,message); 88 break; 89 #ifdef __GNUC__ 90 case 'b': 91 Assert::_my_assert::backtrace(filename,line); 92 break; 93 #endif /* __GNUC__ */ 94 case 'w': 95 ignore = true; 96 // fallthrough 97 case 'i': 98 return false; 99 break; 93 100 } 94 101 } … … 96 103 } 97 104 98 void _my_assert::doHooks(){ 105 #ifdef __GNUC__ 106 void Assert::_my_assert::backtrace(const char *file, int line){ 107 const size_t max_depth = 100; 108 void* stack_addrs[max_depth]; 109 size_t stack_depth; 110 char **stack_strings=0; 111 const char *func_name=0; 112 size_t sz = 64; 113 114 // get the backtrace 115 stack_depth = ::backtrace(stack_addrs,max_depth); 116 stack_strings = backtrace_symbols(stack_addrs, stack_depth); 117 // used later for demangling 118 // reserved here, so we can free it unconditionally 119 char *dm_function = static_cast<char*>(malloc(sz)); 120 if(!dm_function){ 121 // malloc failed... we are out of luck 122 cout << "cannot provide stack trace due to exhausted memory" << endl; 123 return; 124 } 125 126 cout << "Backtrace from " << file << "@" << line << ":" << endl; 127 128 // i=2 because we don't want this function, nor the assertion handler 129 for(unsigned int i=2;i<stack_depth-2;++i){ 130 // find the mangled function name 131 char *begin = stack_strings[i]; 132 // function name starts with a ( 133 while(*begin && *begin!='(') ++begin; 134 char *end=begin; 135 while(*end && *end!='+') ++end; 136 137 // see if we found our function name 138 if(*begin && *end){ 139 *begin++ = 0; 140 *end = 0; 141 // use the C++ demangler 142 143 int status; 144 char *func_ret = abi::__cxa_demangle(begin, dm_function, &sz, &status); 145 if(func_ret){ 146 // abi might have realloced... 147 dm_function = func_ret; 148 func_name = dm_function; 149 } 150 else{ 151 // demangling failed... get the function name without demangling 152 func_name = begin; 153 } 154 } 155 else{ 156 // function name not found... get the whole line 157 func_name = stack_strings[i]; 158 } 159 cout << func_name << endl; 160 } 161 free(dm_function); 162 free(stack_strings); // malloc()ed by backtrace_symbols 163 } 164 #endif /* __GNUC__ */ 165 166 void Assert::_my_assert::doHooks(){ 99 167 for(vector<hook_t>::reverse_iterator iter = hooks.rbegin(); iter!=hooks.rend(); ++iter ){ 100 168 (*iter)(); … … 102 170 } 103 171 104 void _my_assert::addHook(hook_t hook){172 void Assert::_my_assert::addHook(hook_t hook){ 105 173 hooks.push_back(hook); 106 174 } 107 175 108 void _my_assert::removeHook(Assert::hook_t hook){176 void Assert::_my_assert::removeHook(Assert::hook_t hook){ 109 177 for(vector<hook_t>::iterator iter = hooks.begin(); iter!=hooks.end();){ 110 178 if((*iter)==hook){ … … 117 185 } 118 186 119 void _my_assert::setDefault(Assert::Action action){187 void Assert::_my_assert::setDefault(Assert::Action action){ 120 188 defaultAction = action; 121 189 } 122 Assert::Action _my_assert::getDefault(){190 Assert::Action Assert::_my_assert::getDefault(){ 123 191 return defaultAction; 124 192 } 125 std::string _my_assert::printDefault(){193 std::string Assert::_my_assert::printDefault(){ 126 194 return ActionNames[defaultAction]; 127 195 }
Note:
See TracChangeset
for help on using the changeset viewer.