Changeset 257c77 for src/Helpers
- Timestamp:
- Jun 17, 2010, 2:55:56 PM (15 years ago)
- Branches:
- Action_Thermostats, Add_AtomRandomPerturbation, Add_FitFragmentPartialChargesAction, Add_RotateAroundBondAction, Add_SelectAtomByNameAction, Added_ParseSaveFragmentResults, AddingActions_SaveParseParticleParameters, Adding_Graph_to_ChangeBondActions, Adding_MD_integration_tests, Adding_ParticleName_to_Atom, Adding_StructOpt_integration_tests, AtomFragments, Automaking_mpqc_open, AutomationFragmentation_failures, Candidate_v1.5.4, Candidate_v1.6.0, Candidate_v1.6.1, Candidate_v1.7.0, ChangeBugEmailaddress, ChangingTestPorts, ChemicalSpaceEvaluator, CombiningParticlePotentialParsing, Combining_Subpackages, Debian_Package_split, Debian_package_split_molecuildergui_only, Disabling_MemDebug, Docu_Python_wait, EmpiricalPotential_contain_HomologyGraph, EmpiricalPotential_contain_HomologyGraph_documentation, Enable_parallel_make_install, Enhance_userguide, Enhanced_StructuralOptimization, Enhanced_StructuralOptimization_continued, Example_ManyWaysToTranslateAtom, Exclude_Hydrogens_annealWithBondGraph, FitPartialCharges_GlobalError, Fix_BoundInBox_CenterInBox_MoleculeActions, Fix_ChargeSampling_PBC, Fix_ChronosMutex, Fix_FitPartialCharges, Fix_FitPotential_needs_atomicnumbers, Fix_ForceAnnealing, Fix_IndependentFragmentGrids, Fix_ParseParticles, Fix_ParseParticles_split_forward_backward_Actions, Fix_PopActions, Fix_QtFragmentList_sorted_selection, Fix_Restrictedkeyset_FragmentMolecule, Fix_StatusMsg, Fix_StepWorldTime_single_argument, Fix_Verbose_Codepatterns, Fix_fitting_potentials, Fixes, ForceAnnealing_goodresults, ForceAnnealing_oldresults, ForceAnnealing_tocheck, ForceAnnealing_with_BondGraph, ForceAnnealing_with_BondGraph_continued, ForceAnnealing_with_BondGraph_continued_betteresults, ForceAnnealing_with_BondGraph_contraction-expansion, FragmentAction_writes_AtomFragments, FragmentMolecule_checks_bonddegrees, GeometryObjects, Gui_Fixes, Gui_displays_atomic_force_velocity, ImplicitCharges, IndependentFragmentGrids, IndependentFragmentGrids_IndividualZeroInstances, IndependentFragmentGrids_IntegrationTest, IndependentFragmentGrids_Sole_NN_Calculation, JobMarket_RobustOnKillsSegFaults, JobMarket_StableWorkerPool, JobMarket_unresolvable_hostname_fix, MoreRobust_FragmentAutomation, ODR_violation_mpqc_open, PartialCharges_OrthogonalSummation, PdbParser_setsAtomName, PythonUI_with_named_parameters, QtGui_reactivate_TimeChanged_changes, Recreated_GuiChecks, Rewrite_FitPartialCharges, RotateToPrincipalAxisSystem_UndoRedo, SaturateAtoms_findBestMatching, SaturateAtoms_singleDegree, StoppableMakroAction, Subpackage_CodePatterns, Subpackage_JobMarket, Subpackage_LinearAlgebra, Subpackage_levmar, Subpackage_mpqc_open, Subpackage_vmg, Switchable_LogView, ThirdParty_MPQC_rebuilt_buildsystem, TrajectoryDependenant_MaxOrder, TremoloParser_IncreasedPrecision, TremoloParser_MultipleTimesteps, TremoloParser_setsAtomName, Ubuntu_1604_changes, stable
- Children:
- b47bfc
- Parents:
- 992fd7 (diff), 5f5a7b (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - Location:
- src/Helpers
- Files:
-
- 3 edited
-
Assert.cpp (modified) (5 diffs)
-
MemDebug.cpp (modified) (13 diffs)
-
MemDebug.hpp (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/Helpers/Assert.cpp
r992fd7 r257c77 5 5 * Author: crueger 6 6 */ 7 8 #include "Helpers/MemDebug.hpp" 7 9 8 10 #include "Helpers/Assert.hpp" … … 46 48 using namespace Assert; 47 49 50 #ifndef NDEBUG 51 48 52 Action _my_assert::defaultAction = Ask; 49 53 std::vector<Assert::hook_t> _my_assert::hooks; … … 52 56 const char* _wrapper::message_ptr = "source pointer did not point to object of desired type"; 53 57 const char* _wrapper::message_ref = "source reference did not contain object of desired type"; 54 55 58 56 59 … … 63 66 { 64 67 if(!res){ 65 cout << "Assertion " << condition <<" failed in file " << filename << " at line " << line << endl;68 cout << "Assertion \"" << condition << "\" failed in file " << filename << " at line " << line << endl; 66 69 cout << "Assertion Message: " << message << std::endl; 67 70 while(true){ … … 123 126 return ActionNames[defaultAction]; 124 127 } 128 129 #endif 130 -
src/Helpers/MemDebug.cpp
r992fd7 r257c77 6 6 */ 7 7 8 #ifndef NDBEGUG 9 #ifndef NO_MEMDEBUG 10 8 11 #include <iostream> 9 12 #include <cstdlib> … … 11 14 #include <boost/thread.hpp> 12 15 16 #ifdef __GNUC__ 17 #include <execinfo.h> 18 #include <cxxabi.h> 19 #endif 20 13 21 using namespace std; 14 22 15 #ifndef NDBEGUG 16 #ifndef NO_MEMDEBUG 23 // we need our own low level mutexex, since we cannot assure the time of construction and destruction 24 // otherwise 25 #if defined(unix) || defined(__unix) 26 27 #include <pthread.h> 28 #include <cassert> 29 #define mutex_t pthread_mutex_t 30 #define mutex_init PTHREAD_MUTEX_INITIALIZER 31 #define mutex_lock(mtx) \ 32 do{\ 33 int res = pthread_mutex_lock(&(mtx));\ 34 assert(!res && "Could not lock mutex!");\ 35 }while(0) 36 37 #define mutex_unlock(mtx) \ 38 do{\ 39 int res = pthread_mutex_unlock(&(mtx));\ 40 assert(!res && "Could not unlock mutex!");\ 41 }while(0) 42 43 #else 44 # error "No thread structure defined for this plattform..." 45 #endif 17 46 18 47 namespace Memory { … … 34 63 char file[length+1]; 35 64 int line; 65 #ifdef __GNUC__ // function tracking only works with GCC 66 // function names can get looooong 67 enum {length2 = 256}; 68 char function[length2+1]; 69 #endif 36 70 size_t nbytes; 37 71 bool isUsed; … … 44 78 }; 45 79 46 boost::mutex memorylock; 80 81 mutex_t memorylock = mutex_init; 47 82 48 83 // start and end of the doubly-linked list … … 96 131 for(entry_t *pos=begin;pos;pos=pos->next){ 97 132 cout << "\nChunk of " << pos->info.nbytes << " bytes" << " still available" << endl; 133 #ifdef __GNUC__ 134 cout << "Chunk reserved at: " << pos->info.function 135 << " (" << pos->info.file << ":" << pos->info.line << ")" << endl; 136 #else 98 137 cout << "Chunk reserved at: " << pos->info.file << ":" << pos->info.line << endl; 99 } 138 #endif 139 } 140 } 141 142 // Adds an entry to the linked list 143 void addEntry(entry_t *entry){ 144 // check if the entry is already in the list 145 if(!entry->isIgnored) 146 return; 147 148 mutex_lock(Memory::memorylock); 149 150 entry->next=0; // the created block is last in the list 151 entry->prev=Memory::end; // the created block is last in the list 152 if(!Memory::begin){ 153 // the list was empty... start a new one 154 Memory::begin=entry; 155 } 156 else { 157 // other blocks present... we can add to the last one 158 Memory::end->next=entry; 159 } 160 Memory::end=entry; 161 162 // update some global info 163 Memory::state += entry->info.nbytes; 164 if(Memory::state>Memory::max){ 165 Memory::max = Memory::state; 166 } 167 ++Memory::allocs; 168 // done with the list... it is safe to unlock now 169 mutex_unlock(Memory::memorylock); 170 entry->isIgnored = false; 100 171 } 101 172 … … 105 176 return; 106 177 178 mutex_lock(memorylock); 107 179 if(entry->prev){ 108 180 entry->prev->next = entry->next; … … 120 192 end = entry->prev; 121 193 } 194 Memory::state -= entry->info.nbytes; 195 mutex_unlock(memorylock); 122 196 entry->isIgnored = true; 123 Memory::state -= entry->info.nbytes; 197 124 198 } 125 199 … … 130 204 deleteEntry(entry); 131 205 } 132 } 133 134 void *operator new(size_t nbytes,const char* file, int line) throw(std::bad_alloc) { 135 136 // we need to lock, so that no one changes the linked list while we are here 137 boost::mutex::scoped_lock guard(Memory::memorylock); 206 207 #ifdef __GNUC__ 208 // this function let's us find the caller's name 209 char* getCaller(){ 210 // stack looks like this: 211 // getCaller(); 212 // operator new(); 213 // function_we_are_looking_for(); <- 214 const size_t max_depth = 3; 215 void* stack_addrs[max_depth]; 216 size_t stack_depth; 217 char **stack_strings=0; 218 const char *func_name=0; 219 const char *toplevel = "Global scope"; 220 char *retval=0; 221 222 // get the backtrace, depth three 223 stack_depth = backtrace(stack_addrs,max_depth); 224 stack_strings = backtrace_symbols(stack_addrs, stack_depth); 225 // used later for demangling 226 // reserved here, so we can free it unconditionally 227 char *dm_function = static_cast<char*>(malloc(entry_t::info_t::length2)); 228 if(!dm_function){ 229 // malloc failed... we are out of luck 230 throw std::bad_alloc(); 231 } 232 233 // see if we found our function name 234 if(stack_depth==max_depth){ 235 // find the mangled function name 236 char *begin = stack_strings[max_depth-1]; 237 // function name starts with a ( 238 while(*begin && *begin!='(') ++begin; 239 char *end=begin; 240 while(*end && *end!='+') ++end; 241 242 // see if we found our function name 243 if(*begin && *end){ 244 *begin++ = 0; 245 *end = 0; 246 // use the C++ demangler 247 248 size_t sz = entry_t::info_t::length2; 249 int status; 250 char *func_ret = abi::__cxa_demangle(begin, dm_function, &sz, &status); 251 if(func_ret){ 252 // abi might have realloced... 253 dm_function = func_ret; 254 func_name = dm_function; 255 } 256 else{ 257 // demangling failed... get the function name without demangling 258 func_name = begin; 259 } 260 } 261 else{ 262 // function name not found... get the whole line 263 func_name = stack_strings[max_depth-1]; 264 } 265 266 } 267 else{ 268 func_name = toplevel; 269 } 270 271 // now we copy the desired function name 272 if((retval = static_cast<char*>(malloc(strlen(func_name)+1)))){ 273 // we know that the string will fit, so strcpy is safe here 274 strcpy(retval,func_name); 275 } 276 else{ 277 free(stack_strings); // malloc()ed by backtrace_symbols 278 free(dm_function); 279 // uh-uh ... seems we are out of luck for allocations now 280 throw std::bad_alloc(); 281 } 282 free(dm_function); 283 free(stack_strings); // malloc()ed by backtrace_symbols 284 return retval; 285 } 286 #endif 287 } 288 289 #ifdef __GNUC__ 290 291 void *operator new(size_t nbytes,const char* file, int line, const char* func) throw(std::bad_alloc) { 138 292 139 293 // to avoid allocations of 0 bytes if someone screws up … … 153 307 } 154 308 155 // we got the space, so update the global info 156 Memory::state += nbytes; 157 if(Memory::state>Memory::max){ 158 Memory::max = Memory::state; 159 } 160 Memory::allocs++; 309 // build the entry in front of the space 310 Memory::entry_t *entry = (Memory::entry_t*) res; 311 memset(res,0,entrySpace); 312 entry->info.nbytes = nbytes; 313 entry->info.isUsed = true; 314 strncpy(entry->info.file,file,Memory::entry_t::info_t::length); 315 entry->info.file[Memory::entry_t::info_t::length] = '\0'; 316 entry->info.line=line; 317 strncpy(entry->info.function,func,Memory::entry_t::info_t::length2); 318 entry->info.function[Memory::entry_t::info_t::length2] = '\0'; 319 // the space starts behind the info 320 entry->info.location = (char*)res + entrySpace; 321 322 // mark the block as not in the list (will be changed by addEntry) 323 entry->isIgnored = true; 324 Memory::addEntry(entry); 325 326 // get the checksum... 327 entry->checksum = Memory::calcChecksum(&entry->info); 328 329 // ok, space is prepared... the user can have it. 330 // the rest (constructor, deleting when something is thrown etc) 331 // is handled automatically 332 return entry->info.location; 333 } 334 335 #else 336 337 void *operator new(size_t nbytes,const char* file, int line) throw(std::bad_alloc) { 338 339 // to avoid allocations of 0 bytes if someone screws up 340 // allocation with 0 byte size are undefined behavior, so we are 341 // free to handle it this way 342 if(!nbytes) { 343 nbytes = 1; 344 } 345 346 // get the size of the entry, including alignment 347 static const size_t entrySpace = Memory::doAlign(sizeof(Memory::entry_t)); 348 349 void *res; 350 if(!(res=malloc(entrySpace + nbytes))){ 351 // new must throw, when space is low 352 throw std::bad_alloc(); 353 } 161 354 162 355 // build the entry in front of the space … … 171 364 entry->info.location = (char*)res + entrySpace; 172 365 173 // add the entry at the end of the list 174 entry->next=0; // the created block is last in the list 175 entry->prev=Memory::end; // the created block is last in the list 176 if(!Memory::begin){ 177 // the list was empty... start a new one 178 Memory::begin=entry; 179 } 180 else { 181 // other blocks present... we can add to the last one 182 Memory::end->next=entry; 183 } 184 Memory::end=entry; 366 // mark the block as not in the list (will be changed by addEntry) 367 entry->isIgnored = true; 368 Memory::addEntry(entry); 185 369 186 370 // get the checksum... … … 196 380 } 197 381 382 #endif 383 198 384 void *operator new(size_t nbytes) throw(std::bad_alloc) { 199 385 // Just forward to the other operator, when we do not know from 200 386 // where the allocation came 387 #ifdef __GNUC__ 388 // this might throw bad_alloc 389 char *caller = Memory::getCaller(); 390 void* retval = 0; 391 392 // if this throws, we have to clean up the caller anyway 393 try{ 394 retval = operator new(nbytes,"Unknown",0,caller); 395 } 396 catch(...) 397 { 398 free(caller); // malloc()ed by Memory::getCaller(); 399 throw; 400 } 401 free(caller); // malloc()ed by Memory::getCaller(); 402 return retval; 403 #else 201 404 return operator new(nbytes,"Unknown",0); 202 } 405 #endif 406 } 407 408 #ifdef __GNUC__ 409 410 void *operator new[] (size_t nbytes,const char* file, int line, const char* func) throw(std::bad_alloc) { 411 // The difference between new and new[] is just for compiler bookkeeping. 412 return operator new(nbytes,file,line,func); 413 } 414 415 #else 203 416 204 417 void *operator new[] (size_t nbytes,const char* file, int line) throw(std::bad_alloc) { … … 207 420 } 208 421 422 #endif 423 209 424 void *operator new[] (size_t nbytes) throw(std::bad_alloc) { 210 425 // Forward again 426 #ifdef __GNUC__ 427 // this might throw bad_alloc 428 char *caller = Memory::getCaller(); 429 void *retval=0; 430 431 // if this throws, we have to clean up the caller anyway 432 try{ 433 retval = operator new[] (nbytes,"Unknown",0,caller); 434 } 435 catch(...) 436 { 437 free(caller); // malloc()ed by Memory::getCaller(); 438 throw; 439 } 440 free(caller); // malloc()ed by Memory::getCaller(); 441 return retval; 442 #else 211 443 return operator new[] (nbytes,"Unknown",0); 444 #endif 212 445 } 213 446 … … 217 450 return; 218 451 } 219 220 // we need to lock, so the linked list does not changed while we are in here221 boost::mutex::scoped_lock guard(Memory::memorylock);222 452 223 453 // get the size for the entry, including alignment -
src/Helpers/MemDebug.hpp
r992fd7 r257c77 28 28 #endif 29 29 30 #include <cstdlib>31 30 #include <new> 31 32 // some light header files, that do weird new stuff and therefore need 33 // to be loaded before the define 34 #include <string> 35 #include <boost/optional.hpp> 36 #include <boost/shared_ptr.hpp> 37 #include <boost/function.hpp> 38 #include <boost/program_options.hpp> 39 32 40 33 41 namespace Memory { … … 53 61 } 54 62 } 55 63 #ifdef __GNUC__ 64 void *operator new (size_t nbytes,const char* file, int line, const char* func) throw(std::bad_alloc); 65 void *operator new[] (size_t nbytes,const char* file, int line, const char* func) throw(std::bad_alloc); 66 #else 56 67 void *operator new (size_t nbytes,const char* file, int line) throw(std::bad_alloc); 57 68 void *operator new[] (size_t nbytes,const char* file, int line) throw(std::bad_alloc); 69 #endif 58 70 void operator delete (void *ptr,const char*, int) throw(); 59 71 void operator delete[] (void *ptr,const char*, int) throw(); 72 73 60 74 61 75 /** … … 63 77 * version that allows tracking. 64 78 */ 79 #ifdef __GNUC__ 80 #define new new(__FILE__,__LINE__,__PRETTY_FUNCTION__) 81 #else 65 82 #define new new(__FILE__,__LINE__) 83 #endif 66 84 67 85 #endif 68 86 #endif 69 87 88 89 #ifdef NDEBUG 90 #undef MEMDEBUG 91 #endif 70 92 71 93 #ifndef MEMDEBUG
Note:
See TracChangeset
for help on using the changeset viewer.
