Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Helpers/Assert.cpp

    r112b09 r506d2f  
    55 *      Author: crueger
    66 */
    7 
    8 #include "Helpers/MemDebug.hpp"
    97
    108#include "Helpers/Assert.hpp"
     
    4644}
    4745
    48 using namespace Assert;
    49 
    5046#ifndef NDEBUG
    5147
    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
    5453
    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";
     54Assert::Action Assert::_my_assert::defaultAction = Ask;
     55std::vector<Assert::hook_t> Assert::_my_assert::hooks;
    5856
     57std::map<std::string,bool> Assert::_wrapper::ignores;
     58const char* Assert::_wrapper::message_ptr = "source pointer did not point to object of desired type";
     59const char* Assert::_wrapper::message_ref = "source reference did not contain object of desired type";
    5960
    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)
     61bool Assert::_my_assert::check(const char* condition,
     62                               const char* message,
     63                               const char* filename,
     64                               const int line,
     65                               bool& ignore)
    6666{
    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;
    93100    }
    94101  }
     
    96103}
    97104
    98 void _my_assert::doHooks(){
     105#ifdef __GNUC__
     106void 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
     166void Assert::_my_assert::doHooks(){
    99167  for(vector<hook_t>::reverse_iterator iter = hooks.rbegin(); iter!=hooks.rend(); ++iter ){
    100168    (*iter)();
     
    102170}
    103171
    104 void _my_assert::addHook(hook_t hook){
     172void Assert::_my_assert::addHook(hook_t hook){
    105173  hooks.push_back(hook);
    106174}
    107175
    108 void _my_assert::removeHook(Assert::hook_t hook){
     176void Assert::_my_assert::removeHook(Assert::hook_t hook){
    109177  for(vector<hook_t>::iterator iter = hooks.begin(); iter!=hooks.end();){
    110178    if((*iter)==hook){
     
    117185}
    118186
    119 void _my_assert::setDefault(Assert::Action action){
     187void Assert::_my_assert::setDefault(Assert::Action action){
    120188  defaultAction = action;
    121189}
    122 Assert::Action _my_assert::getDefault(){
     190Assert::Action Assert::_my_assert::getDefault(){
    123191  return defaultAction;
    124192}
    125 std::string _my_assert::printDefault(){
     193std::string Assert::_my_assert::printDefault(){
    126194  return ActionNames[defaultAction];
    127195}
Note: See TracChangeset for help on using the changeset viewer.