/* * Project: MoleCuilder * Description: creates and alters molecular systems * Copyright (C) 2010 University of Bonn. All rights reserved. * Please see the LICENSE file or "Copyright notice" in builder.cpp for details. */ /* * Assert.cpp * * Created on: Mar 18, 2010 * Author: crueger */ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include "Helpers/MemDebug.hpp" #include "Helpers/Assert.hpp" #include using namespace std; namespace Assert{ AssertionFailure::AssertionFailure(std::string _condition, std::string _file, int _line, std::string _message) : condition(_condition), file(_file), line(_line), message(_message) {} std::string AssertionFailure::getFile(){ return file; } int AssertionFailure::getLine(){ return line; } std::string AssertionFailure::getMessage(){ return message; } std::ostream& AssertionFailure::operator<<(std::ostream& out){ out << "Assertion \"" << condition << "\" failed in file " << file << " at line " << line << endl; out << "Assertion Message: " << message << std::endl; return out; } const char ActionKeys[] = {'\0','a','t','i'}; const char* ActionNames[] = {"Ask","Abort","Throw","Ignore"}; } #ifndef NDEBUG #ifdef __GNUC__ #include #include #include #endif Assert::Action Assert::_my_assert::defaultAction = Ask; std::vector Assert::_my_assert::hooks; std::map Assert::_wrapper::ignores; const char* Assert::_wrapper::message_ptr = "source pointer did not point to object of desired type"; const char* Assert::_wrapper::message_ref = "source reference did not contain object of desired type"; bool Assert::_my_assert::check(const char* condition, std::string message, const char* filename, const int line, bool& ignore) { cout << "Assertion \"" << condition << "\" failed in file " << filename << " at line " << line << endl; cout << "Assertion Message: " << message << std::endl; while(true){ char choice; if(defaultAction==Assert::Ask) { #ifdef __GNUC__ cout << "Please choose: (a)bort, (t)hrow execption, show (b)actrace, (i)gnore, al(w)ays ignore" << endl; #else cout << "Please choose: (a)bort, (t)hrow execption, (i)gnore, al(w)ays ignore" << endl; #endif /* __GNUC__ */ cin >> choice; } else{ choice = ActionKeys[defaultAction]; } switch(choice){ case 'a': return true; break; case 't': throw AssertionFailure(condition,filename,line,message); break; #ifdef __GNUC__ case 'b': Assert::_my_assert::backtrace(filename,line); break; #endif /* __GNUC__ */ case 'w': ignore = true; // fallthrough case 'i': return false; break; } } return false; } #ifdef __GNUC__ void Assert::_my_assert::backtrace(const char *file, int line){ const size_t max_depth = 100; void* stack_addrs[max_depth]; size_t stack_depth; char **stack_strings=0; const char *func_name=0; size_t sz = 64; // get the backtrace stack_depth = ::backtrace(stack_addrs,max_depth); stack_strings = backtrace_symbols(stack_addrs, stack_depth); // used later for demangling // reserved here, so we can free it unconditionally char *dm_function = static_cast(malloc(sz)); if(!dm_function){ // malloc failed... we are out of luck cout << "cannot provide stack trace due to exhausted memory" << endl; return; } cout << "Backtrace from " << file << "@" << line << ":" << endl; // i=2 because we don't want this function, nor the assertion handler for(unsigned int i=2;i::reverse_iterator iter = hooks.rbegin(); iter!=hooks.rend(); ++iter ){ (*iter)(); } } void Assert::_my_assert::addHook(hook_t hook){ hooks.push_back(hook); } void Assert::_my_assert::removeHook(Assert::hook_t hook){ for(vector::iterator iter = hooks.begin(); iter!=hooks.end();){ if((*iter)==hook){ iter = hooks.erase(iter); } else{ ++iter; } } } void Assert::_my_assert::setDefault(Assert::Action action){ defaultAction = action; } Assert::Action Assert::_my_assert::getDefault(){ return defaultAction; } std::string Assert::_my_assert::printDefault(){ return ActionNames[defaultAction]; } #endif