Changeset 257c77 for src/Helpers


Ignore:
Timestamp:
Jun 17, 2010, 2:55:56 PM (15 years ago)
Author:
Tillmann Crueger <crueger@…>
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.
Message:

Merge branch 'stable' into QT4Refactoring

Conflicts:

molecuilder/src/Actions/TesselationAction/ConvexEnvelopeAction.hpp
molecuilder/src/Helpers/MemDebug.hpp
molecuilder/src/Makefile.am
molecuilder/src/UIElements/Dialog.cpp
molecuilder/src/UIElements/MainWindow.cpp
molecuilder/src/UIElements/TextUI/TextUIFactory.cpp
molecuilder/src/builder.cpp

Location:
src/Helpers
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/Helpers/Assert.cpp

    r992fd7 r257c77  
    55 *      Author: crueger
    66 */
     7
     8#include "Helpers/MemDebug.hpp"
    79
    810#include "Helpers/Assert.hpp"
     
    4648using namespace Assert;
    4749
     50#ifndef NDEBUG
     51
    4852Action _my_assert::defaultAction = Ask;
    4953std::vector<Assert::hook_t> _my_assert::hooks;
     
    5256const char* _wrapper::message_ptr = "source pointer did not point to object of desired type";
    5357const char* _wrapper::message_ref = "source reference did not contain object of desired type";
    54 
    5558
    5659
     
    6366{
    6467  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;
    6669    cout << "Assertion Message: " << message << std::endl;
    6770    while(true){
     
    123126  return ActionNames[defaultAction];
    124127}
     128
     129#endif
     130
  • src/Helpers/MemDebug.cpp

    r992fd7 r257c77  
    66 */
    77
     8#ifndef NDBEGUG
     9#ifndef NO_MEMDEBUG
     10
    811#include <iostream>
    912#include <cstdlib>
     
    1114#include <boost/thread.hpp>
    1215
     16#ifdef __GNUC__
     17#include <execinfo.h>
     18#include <cxxabi.h>
     19#endif
     20
    1321using namespace std;
    1422
    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
    1746
    1847namespace Memory {
     
    3463      char file[length+1];
    3564      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
    3670      size_t nbytes;
    3771      bool isUsed;
     
    4478  };
    4579
    46   boost::mutex memorylock;
     80
     81  mutex_t memorylock = mutex_init;
    4782
    4883  // start and end of the doubly-linked list
     
    96131    for(entry_t *pos=begin;pos;pos=pos->next){
    97132      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
    98137      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;
    100171  }
    101172
     
    105176      return;
    106177
     178    mutex_lock(memorylock);
    107179    if(entry->prev){
    108180      entry->prev->next = entry->next;
     
    120192      end = entry->prev;
    121193    }
     194    Memory::state  -= entry->info.nbytes;
     195    mutex_unlock(memorylock);
    122196    entry->isIgnored = true;
    123     Memory::state  -= entry->info.nbytes;
     197
    124198  }
    125199
     
    130204    deleteEntry(entry);
    131205  }
    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
     291void *operator new(size_t nbytes,const char* file, int line, const char* func) throw(std::bad_alloc) {
    138292
    139293  // to avoid allocations of 0 bytes if someone screws up
     
    153307  }
    154308
    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
     337void *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  }
    161354
    162355  // build the entry in front of the space
     
    171364  entry->info.location = (char*)res + entrySpace;
    172365
    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);
    185369
    186370  // get the checksum...
     
    196380}
    197381
     382#endif
     383
    198384void *operator new(size_t nbytes) throw(std::bad_alloc) {
    199385  // Just forward to the other operator, when we do not know from
    200386  // 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
    201404  return operator new(nbytes,"Unknown",0);
    202 }
     405#endif
     406}
     407
     408#ifdef __GNUC__
     409
     410void *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
    203416
    204417void *operator new[] (size_t nbytes,const char* file, int line) throw(std::bad_alloc) {
     
    207420}
    208421
     422#endif
     423
    209424void *operator new[] (size_t nbytes) throw(std::bad_alloc) {
    210425  // 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
    211443  return operator new[] (nbytes,"Unknown",0);
     444#endif
    212445}
    213446
     
    217450    return;
    218451  }
    219 
    220   // we need to lock, so the linked list does not changed while we are in here
    221   boost::mutex::scoped_lock guard(Memory::memorylock);
    222452
    223453  // get the size for the entry, including alignment
  • src/Helpers/MemDebug.hpp

    r992fd7 r257c77  
    2828#endif
    2929
    30 #include <cstdlib>
    3130#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
    3240
    3341namespace Memory {
     
    5361  }
    5462}
    55 
     63#ifdef __GNUC__
     64void *operator new   (size_t nbytes,const char* file, int line, const char* func) throw(std::bad_alloc);
     65void *operator new[] (size_t nbytes,const char* file, int line, const char* func) throw(std::bad_alloc);
     66#else
    5667void *operator new   (size_t nbytes,const char* file, int line) throw(std::bad_alloc);
    5768void *operator new[] (size_t nbytes,const char* file, int line) throw(std::bad_alloc);
     69#endif
    5870void operator delete   (void *ptr,const char*, int) throw();
    5971void operator delete[] (void *ptr,const char*, int) throw();
     72
     73
    6074
    6175/**
     
    6377 * version that allows tracking.
    6478 */
     79#ifdef __GNUC__
     80#define new new(__FILE__,__LINE__,__PRETTY_FUNCTION__)
     81#else
    6582#define new new(__FILE__,__LINE__)
     83#endif
    6684
    6785#endif
    6886#endif
    6987
     88
     89#ifdef NDEBUG
     90#undef MEMDEBUG
     91#endif
    7092
    7193#ifndef MEMDEBUG
Note: See TracChangeset for help on using the changeset viewer.