X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fpbd%2Fboost_debug.cc;h=e1c6571f9cf135fcaacff22afb99351c2ee16802;hb=00caabf73583fa029601b7d4e9ccdb9b2da7925c;hp=c9487197e111ffdeee6aa888229ef7a528fd029d;hpb=e5b6e06f837d8b0d3fdb89621d3a3703dc5a29a3;p=ardour.git diff --git a/libs/pbd/boost_debug.cc b/libs/pbd/boost_debug.cc index c9487197e1..e1c6571f9c 100644 --- a/libs/pbd/boost_debug.cc +++ b/libs/pbd/boost_debug.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2009 Paul Davis + Copyright (C) 2009 Paul Davis From an idea by Carl Hetherington. This program is free software; you can redistribute it and/or modify @@ -29,10 +29,11 @@ #include #include #include -#include +#include #include #include "pbd/stacktrace.h" +#include "pbd/boost_debug.h" class Backtrace { public: @@ -47,8 +48,8 @@ private: std::ostream& operator<< (std::ostream& str, const Backtrace& bt) { return bt.print (str); } -Backtrace::Backtrace() -{ +Backtrace::Backtrace() +{ #ifdef HAVE_EXECINFO size = ::backtrace (trace, 200); #endif @@ -63,9 +64,9 @@ Backtrace::print (std::ostream& str) const if (size) { #ifdef HAVE_EXECINFO strings = ::backtrace_symbols (trace, size); -#endif +#endif if (strings) { - for (i = 5; i < 5+18 && i < size; i++) { + for (i = 3; i < 5+18 && i < size; i++) { str << strings[i] << std::endl; } free (strings); @@ -75,7 +76,7 @@ Backtrace::print (std::ostream& str) const return str; } -struct BTPair { +struct BTPair { Backtrace* ref; Backtrace* rel; @@ -93,10 +94,10 @@ std::ostream& operator<<(std::ostream& str, const BTPair& btp) { return str; } -struct SPDebug { +struct SPDebug { Backtrace* constructor; Backtrace* destructor; - + SPDebug (Backtrace* c) : constructor (c), destructor (0) {} ~SPDebug () { delete constructor; @@ -119,10 +120,30 @@ typedef std::map IPointerMap; using namespace std; -PointerMap sptrs; -IPointerMap interesting_pointers; +static PointerMap* _sptrs; +PointerMap& sptrs() { + if (_sptrs == 0) { + _sptrs = new PointerMap; + } + return *_sptrs; +} + +static IPointerMap* _interesting_pointers; +IPointerMap& interesting_pointers() { + if (_interesting_pointers == 0) { + _interesting_pointers = new IPointerMap; + } + return *_interesting_pointers; +} + +static Glib::Threads::Mutex* _the_lock; +static Glib::Threads::Mutex& the_lock() { + if (_the_lock == 0) { + _the_lock = new Glib::Threads::Mutex; + } + return *_the_lock; +} -static Glib::StaticMutex the_lock; static bool is_interesting_object (void const* ptr) @@ -130,103 +151,213 @@ is_interesting_object (void const* ptr) if (ptr == 0) { return false; } - - return interesting_pointers.find (ptr) != interesting_pointers.end(); + + return interesting_pointers().find (ptr) != interesting_pointers().end(); } /* ------------------------------- */ +static bool debug_out = false; + +void +boost_debug_shared_ptr_show_live_debugging (bool yn) +{ + debug_out = yn; +} + void boost_debug_shared_ptr_mark_interesting (void* ptr, const char* type) { - Glib::Mutex::Lock guard (the_lock); + Glib::Threads::Mutex::Lock guard (the_lock()); pair newpair (ptr, type); - interesting_pointers.insert (newpair); + interesting_pointers().insert (newpair); + if (debug_out) { + cerr << "Interesting object @ " << ptr << " of type " << type << endl; + } } void -boost_debug_shared_ptr_operator_equals (void const *sp, void const *obj, int) +boost_debug_shared_ptr_operator_equals (void const *sp, void const *old_obj, int old_use_count, void const *obj, int new_use_count) { + if (old_obj == 0 && obj == 0) { + return; + } + + Glib::Threads::Mutex::Lock guard (the_lock()); + + if (is_interesting_object (old_obj) || is_interesting_object (obj)) { + if (debug_out) { + cerr << "ASSIGN SWAPS " << old_obj << " & " << obj << endl; + } + } + + if (is_interesting_object (old_obj)) { + if (debug_out) { + cerr << "\tlost old sp @ " << sp << " for " << old_obj << " UC = " << old_use_count << " now for " << obj << " UC = " << new_use_count + << " (total sp's = " << sptrs().size() << ')' << endl; + } + PointerMap::iterator x = sptrs().find (sp); + + if (x != sptrs().end()) { + sptrs().erase (x); + if (debug_out) { + cerr << "\tRemoved (by assignment) sp for " << old_obj << " @ " << sp << " UC = " << old_use_count << " (total sp's = " << sptrs().size() << ')' << endl; + } + } + } + if (is_interesting_object (obj)) { - cerr << "sp @ " << sp << " assigned\n"; + + pair newpair; + + newpair.first = sp; + newpair.second = new SPDebug (new Backtrace()); + + sptrs().insert (newpair); + + if (debug_out) { + cerr << "assignment created sp for " << obj << " @ " << sp << " used to point to " << old_obj << " UC = " << old_use_count + << " UC = " << new_use_count + << " (total sp's = " << sptrs().size() << ')' << endl; + cerr << *newpair.second << endl; + } } } void -boost_debug_shared_ptr_reset (void const *sp, void const *obj, int) +boost_debug_shared_ptr_reset (void const *sp, void const *old_obj, int old_use_count, void const *obj, int new_use_count) { + if (old_obj == 0 && obj == 0) { + return; + } + + Glib::Threads::Mutex::Lock guard (the_lock()); + + if (is_interesting_object (old_obj) || is_interesting_object (obj)) { + if (debug_out) { + cerr << "RESET SWAPS " << old_obj << " & " << obj << endl; + } + } + + if (is_interesting_object (old_obj)) { + if (debug_out) { + cerr << "\tlost old sp @ " << sp << " for " << old_obj << " UC = " << old_use_count << " now for " << obj << " UC = " << new_use_count + << " (total sp's = " << sptrs().size() << ')' << endl; + } + PointerMap::iterator x = sptrs().find (sp); + + if (x != sptrs().end()) { + sptrs().erase (x); + if (debug_out) { + cerr << "\tRemoved (by reset) sp for " << old_obj << " @ " << sp << " UC = " << old_use_count << " (total sp's = " << sptrs().size() << ')' << endl; + } + } + } + if (is_interesting_object (obj)) { - cerr << "sp @ " << sp << " reset\n"; + + pair newpair; + + newpair.first = sp; + newpair.second = new SPDebug (new Backtrace()); + + sptrs().insert (newpair); + + if (debug_out) { + cerr << "reset created sp for " << obj << " @ " << sp << " used to point to " << old_obj << " UC = " << old_use_count + << " UC = " << new_use_count + << " (total sp's = " << sptrs().size() << ')' << endl; + cerr << *newpair.second << endl; + } } } void boost_debug_shared_ptr_destructor (void const *sp, void const *obj, int use_count) { - Glib::Mutex::Lock guard (the_lock); - PointerMap::iterator x = sptrs.find (sp); + Glib::Threads::Mutex::Lock guard (the_lock()); + PointerMap::iterator x = sptrs().find (sp); - if (x != sptrs.end()) { - sptrs.erase (x); + if (x != sptrs().end()) { + sptrs().erase (x); + if (debug_out) { + cerr << "Removed sp for " << obj << " @ " << sp << " UC = " << use_count << " (total sp's = " << sptrs().size() << ')' << endl; + } } } + void boost_debug_shared_ptr_constructor (void const *sp, void const *obj, int use_count) { - if (is_interesting_object (obj)) { - Glib::Mutex::Lock guard (the_lock); + Glib::Threads::Mutex::Lock guard (the_lock()); pair newpair; newpair.first = sp; newpair.second = new SPDebug (new Backtrace()); - sptrs.insert (newpair); + sptrs().insert (newpair); + if (debug_out) { + cerr << "Stored constructor for " << obj << " @ " << sp << " UC = " << use_count << " (total sp's = " << sptrs().size() << ')' << endl; + cerr << *newpair.second << endl; + } } } +void +boost_debug_count_ptrs () +{ + Glib::Threads::Mutex::Lock guard (the_lock()); + // cerr << "Tracking " << interesting_pointers().size() << " interesting objects with " << sptrs().size () << " shared ptrs\n"; +} + void boost_debug_list_ptrs () { - Glib::Mutex::Lock guard (the_lock); - for (PointerMap::iterator x = sptrs.begin(); x != sptrs.end(); ++x) { - cerr << "Shared ptr @ " << x->first << " history: " - << *x->second - << endl; + Glib::Threads::Mutex::Lock guard (the_lock()); + + if (sptrs().empty()) { + cerr << "There are no dangling shared ptrs\n"; + } else { + for (PointerMap::iterator x = sptrs().begin(); x != sptrs().end(); ++x) { + cerr << "Shared ptr @ " << x->first << " history: " + << *x->second + << endl; + } } } namespace boost { -void sp_scalar_constructor_hook( void * object, std::size_t size, void * pn ) +void sp_scalar_constructor_hook( void *, std::size_t, void *) { } -void sp_scalar_destructor_hook( void * object, std::size_t size, void * pn ) +void sp_scalar_destructor_hook( void *, std::size_t, void *) { } -void sp_counter_ref_hook (void* pn, long use_count) +void sp_counter_ref_hook (void* /*pn*/, long /* use count */) { } -void sp_counter_release_hook (void* pn, long use_count) +void sp_counter_release_hook (void* /*pn*/, long /*use_count*/) { } -void sp_array_constructor_hook(void * p) +void sp_array_constructor_hook(void *) { } -void sp_array_destructor_hook(void * p) +void sp_array_destructor_hook(void *) { } -void sp_scalar_constructor_hook(void * p) +void sp_scalar_constructor_hook(void *) { } -void sp_scalar_destructor_hook(void * p) +void sp_scalar_destructor_hook(void *) { }