2 Copyright (C) 2009 Paul Davis
3 From an idea by Carl Hetherington.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include "libpbd-config.h"
32 #include <glibmm/thread.h>
33 #include <boost/shared_ptr.hpp>
35 #include "pbd/stacktrace.h"
40 std::ostream& print (std::ostream& str) const;
47 std::ostream& operator<< (std::ostream& str, const Backtrace& bt) { return bt.print (str); }
50 Backtrace::Backtrace()
53 size = ::backtrace (trace, 200);
58 Backtrace::print (std::ostream& str) const
65 strings = ::backtrace_symbols (trace, size);
68 for (i = 3; i < 5+18 && i < size; i++) {
69 str << strings[i] << std::endl;
83 BTPair (Backtrace* bt) : ref (bt), rel (0) {}
88 std::ostream& operator<<(std::ostream& str, const BTPair& btp) {
89 str << "*********************************************\n";
90 if (btp.ref) str << *btp.ref << std::endl;
92 if (btp.rel) str << *btp.rel << std::endl;
97 Backtrace* constructor;
98 Backtrace* destructor;
100 SPDebug (Backtrace* c) : constructor (c), destructor (0) {}
107 std::ostream& operator<< (std::ostream& str, const SPDebug& spd)
109 str << "Constructor :" << std::endl;
110 if (spd.constructor) {
111 str << *spd.constructor << std::endl;
117 typedef std::multimap<void const*,SPDebug*> PointerMap;
118 typedef std::map<void const*,const char*> IPointerMap;
123 IPointerMap interesting_pointers;
125 static Glib::StaticMutex the_lock;
128 is_interesting_object (void const* ptr)
134 return interesting_pointers.find (ptr) != interesting_pointers.end();
137 /* ------------------------------- */
139 static bool debug_out = false;
142 boost_debug_shared_ptr_show_live_debugging (bool yn)
148 boost_debug_shared_ptr_mark_interesting (void* ptr, const char* type)
150 Glib::Mutex::Lock guard (the_lock);
151 pair<void*,const char*> newpair (ptr, type);
152 interesting_pointers.insert (newpair);
154 cerr << "Interesting object @ " << ptr << " of type " << type << endl;
159 boost_debug_shared_ptr_operator_equals (void const *sp, void const *old_obj, int old_use_count, void const *obj, int new_use_count)
161 if (old_obj == 0 && obj == 0) {
165 Glib::Mutex::Lock guard (the_lock);
167 if (is_interesting_object (old_obj) || is_interesting_object (obj)) {
169 cerr << "ASSIGN SWAPS " << old_obj << " & " << obj << endl;
173 if (is_interesting_object (old_obj)) {
175 cerr << "\tlost old sp @ " << sp << " for " << old_obj << " UC = " << old_use_count << " now for " << obj << " UC = " << new_use_count
176 << " (total sp's = " << sptrs.size() << ')' << endl;
178 PointerMap::iterator x = sptrs.find (sp);
180 if (x != sptrs.end()) {
183 cerr << "\tRemoved (by assigment) sp for " << old_obj << " @ " << sp << " UC = " << old_use_count << " (total sp's = " << sptrs.size() << ')' << endl;
188 if (is_interesting_object (obj)) {
190 pair<void const*, SPDebug*> newpair;
193 newpair.second = new SPDebug (new Backtrace());
195 sptrs.insert (newpair);
198 cerr << "assignment created sp for " << obj << " @ " << sp << " used to point to " << old_obj << " UC = " << old_use_count
199 << " UC = " << new_use_count
200 << " (total sp's = " << sptrs.size() << ')' << endl;
201 cerr << *newpair.second << endl;
207 boost_debug_shared_ptr_reset (void const *sp, void const *old_obj, int old_use_count, void const *obj, int new_use_count)
209 if (old_obj == 0 && obj == 0) {
213 Glib::Mutex::Lock guard (the_lock);
215 if (is_interesting_object (old_obj) || is_interesting_object (obj)) {
217 cerr << "RESET SWAPS " << old_obj << " & " << obj << endl;
221 if (is_interesting_object (old_obj)) {
223 cerr << "\tlost old sp @ " << sp << " for " << old_obj << " UC = " << old_use_count << " now for " << obj << " UC = " << new_use_count
224 << " (total sp's = " << sptrs.size() << ')' << endl;
226 PointerMap::iterator x = sptrs.find (sp);
228 if (x != sptrs.end()) {
231 cerr << "\tRemoved (by reset) sp for " << old_obj << " @ " << sp << " UC = " << old_use_count << " (total sp's = " << sptrs.size() << ')' << endl;
236 if (is_interesting_object (obj)) {
238 pair<void const*, SPDebug*> newpair;
241 newpair.second = new SPDebug (new Backtrace());
243 sptrs.insert (newpair);
246 cerr << "reset created sp for " << obj << " @ " << sp << " used to point to " << old_obj << " UC = " << old_use_count
247 << " UC = " << new_use_count
248 << " (total sp's = " << sptrs.size() << ')' << endl;
249 cerr << *newpair.second << endl;
255 boost_debug_shared_ptr_destructor (void const *sp, void const *obj, int use_count)
257 Glib::Mutex::Lock guard (the_lock);
258 PointerMap::iterator x = sptrs.find (sp);
260 if (x != sptrs.end()) {
263 cerr << "Removed sp for " << obj << " @ " << sp << " UC = " << use_count << " (total sp's = " << sptrs.size() << ')' << endl;
269 boost_debug_shared_ptr_constructor (void const *sp, void const *obj, int use_count)
271 if (is_interesting_object (obj)) {
272 Glib::Mutex::Lock guard (the_lock);
273 pair<void const*, SPDebug*> newpair;
276 newpair.second = new SPDebug (new Backtrace());
278 sptrs.insert (newpair);
280 cerr << "Stored constructor for " << obj << " @ " << sp << " UC = " << use_count << " (total sp's = " << sptrs.size() << ')' << endl;
281 cerr << *newpair.second << endl;
287 boost_debug_count_ptrs ()
289 Glib::Mutex::Lock guard (the_lock);
290 // cerr << "Tracking " << interesting_pointers.size() << " interesting objects with " << sptrs.size () << " shared ptrs\n";
294 boost_debug_list_ptrs ()
296 Glib::Mutex::Lock guard (the_lock);
299 cerr << "There are no dangling shared ptrs\n";
301 for (PointerMap::iterator x = sptrs.begin(); x != sptrs.end(); ++x) {
302 cerr << "Shared ptr @ " << x->first << " history: "
311 void sp_scalar_constructor_hook( void * object, std::size_t size, void * pn )
315 void sp_scalar_destructor_hook( void * object, std::size_t size, void * pn )
319 void sp_counter_ref_hook (void* pn, long use_count)
323 void sp_counter_release_hook (void* pn, long use_count)
327 void sp_array_constructor_hook(void * p)
331 void sp_array_destructor_hook(void * p)
335 void sp_scalar_constructor_hook(void * p)
339 void sp_scalar_destructor_hook(void * p)