Boost logo

Boost Users :

Subject: Re: [Boost-users] [smart_ptr] Problem with circular reference detection
From: Peter Dimov (pdimov_at_[hidden])
Date: 2008-09-16 13:57:29


Jim Barry:
>I am trying to detect circular references using the
>find_unreachable_objects function in sp_collector.cpp. However, it reports
>false positives in the simple case of one object being owned by another. To
>illustrate:
>
> #define BOOST_SP_ENABLE_DEBUG_HOOKS
> #include <boost/shared_ptr.hpp>
>
> // sp_collector.cpp exported functions
> std::size_t find_unreachable_objects(bool report);
>
> struct X {};
>
> struct Y
> {
> boost::shared_ptr<X> pX;
>
> Y() : pX(new X) {}
> };
>
> int main()
> {
> boost::shared_ptr<Y> y(new Y);
> find_unreachable_objects(true);
> return 0;
> }
>
> The output is as follows:
>
> ... 2 objects in m.
> ... 1 objects in m2.
> ... 1 objects in open.
> Unreachable object at 0036BA60, 12 bytes long.
>
> Clearly this is incorrect as there are no circular references. Looking at
> the code, there is what appears to be a typo at line 124:
>
> std::cout << "... " << m2.size() << " objects in open.\n";
>
> should be:
>
> std::cout << "... " << open.size() << " objects in open.\n";
>
> But the real problem seems to be at line 121:
>
> if(p->use_count() != i->second) open.push_back(p);
>
> I'm not entirely sure what's going on in this section of code, but it ends
> up determining (incorrectly) that the "X" object is unreachable. Is there
> any way to get this working properly?

I admit that I don't remember what I was thinking when I wrote
sp_collector.cpp in 2002-2003, but the following patch does seem to fix the
problem with your example. Can you please confirm that it also works for
more complicated cases?

Index: sp_collector.cpp
===================================================================
--- sp_collector.cpp (revision 48405)
+++ sp_collector.cpp (working copy)
@@ -104,6 +104,8 @@

             BOOST_ASSERT(p->use_count() != 0); // there should be no
inactive counts in the map

+ m2[ i->first ];
+
             scan_and_count(i->second.first, i->second.second, m, m2);
         }

@@ -121,7 +123,7 @@
             if(p->use_count() != i->second) open.push_back(p);
         }

- std::cout << "... " << m2.size() << " objects in open.\n";
+ std::cout << "... " << open.size() << " objects in open.\n";

         for(open_type::iterator j = open.begin(); j != open.end(); ++j)
         {


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net