
hi all, quick question concerning shared_ptr... not sure if things get deleted (destroyed) properly and its freaking me out. I hope this is not too long Basically, I use the BGL to store my data and that seems to be ok. The way the BGL stuff is defined is as such... Note that spObjectNode is defined as typedef boost::shared_ptr<CObject> spObjectNode // Set vertex properties typedef boost::property<boost::vertex_name_t, std::string> node_name_t; typedef boost::property<graph_node_t, spObjectNode, node_name_t> node_property_t; // Set edge properties typedef boost::property<boost::edge_name_t, std::string> connection_name_t; typedef boost::property<graph_connection_t, spObjectNode, connection_name_t> edge_property_t; // Set graph typedef adjacency_list<listS, vecS, bidirectionalS, node_property_t, edge_property_t> graph_t; // graph_t m_Graph; The function below is what I use to add a node to the BGL... template <typename T> void AddNode(const T& object) { // Create the vertex boost::shared_ptr<T> pNode(new T(object)); // Add the vertex + its name to the graph vertexdescriptor_t newNode = boost::add_vertex(node_property_t(pNode, node_name_t(pNode->GetObjectName())), m_Graph); }; The way I use the AddNode ... for example in a main.cpp: /// blablabla above CSphere sphere("sphere1"); CSceneDB::Instance().AddNode(sphere); return 0; For testing purposes, in the base class and derived classes (see below) I print a message in the destructor of the class, just to make sure things are ok. If I just have in my main the previous call then upon exit I expect and get the following message... CSceneDB cleanup CSphere cleanup CGeometry cleanup CObject cleanup Now for the source of my anxiety... I wrote a function to get back my object from the BGL and it goes like this... inline boost::shared_ptr<CObject> getNodeProperty(const vertexdescriptor_t& vertex) { boost::property_map<graph_t, graph_node_t>::type node_prop_map; node_prop_map = boost::get(graph_node_t(), m_Graph); return node_prop_map[vertex]; } boost::shared_ptr<CObject> CSceneDB::getNodebyName(const std::string& strName) { boost::shared_ptr<CObject> node_prop; boost::graph_traits<graph_t>::vertex_iterator vi, vi_end; boost::tie(vi, vi_end) = boost::vertices(m_Graph); for(; vi != vi_end; ++vi) { node_prop = getNodeProperty(*vi); if(node_prop != 0) { if(node_prop->GetObjectName() == strName) break; } } return node_prop; } template <typename T> boost::shared_ptr<T> getNode(const std::string& strName) { boost::shared_ptr<CObject> abc = getNodebyName(strName); shared_ptr<T> def = boost::dynamic_pointer_cast<T>(abc); return def; } The problem is that if I do something like this... in the main.cpp /// blablabla stuff above CSphere sphere("sphere1"); CSceneDB::Instance().AddNode(sphere); boost::shared_ptr<CSphere> abc = CSceneDB::Instance().getNode<CSphere>("sphere1"); return 0; I only get upon exit... CSceneDB cleanup what happened to CSphere cleanup, CGeometry cleanup and CObject cleanup, are they leaking? Now for a sanity check, if I do in the main.cpp ... i do NOT do the assignment boost::shared_ptr<CSphere> abc = /// blablabla stuff above CSphere sphere("sphere1"); CSceneDB::Instance().AddNode(sphere); CSceneDB::Instance().getNode<CSphere>("sphere1"); return 0; upon exit i get ... CSceneDB cleanup CSphere cleanup CGeometry cleanup CObject cleanup Can someone tell me why this is, is my assignment wrong? Any help would be greatly appreciated Eric Brief description of the classes used ofr my test // Object.h class CObject { protected: CObject(){}; protected: virtual ~CObject(){cout << "CObject cleanup" << endl;}; }; typedef boost::shared_ptr<CObject> spObjectNode; // Geometry.h class CGeometry : public CObject { protected: CGeometry(){}; protected: virtual ~CGeometry(){cout << "CGeometry cleanup" << endl;}; }; // Sphere.h class CSphere : public CGeometry { public: CSphere(){}; ~CSphere(){cout << "CSphere cleanup" << endl;}; };

again, hi all.... After writing an example to demonstrate the problem, as per Peter's request, I could not repro it, until I added this extra line glutMainLoop(); before the return 0; of main.cpp. As for those how might not know that glutMainLoop does.... Enters the GLUT event processing loop, never to return. One would use the GLUT library when writing OpenGL applications. If I comment out this line, then I can account for every single class destructor call, i.e. no leaks. When it is NOT commented, then most of the class destructor calls do not get called, or printed (this I will verify) and therefore my guess is that there are leaks. Anyway, since I have done the work to write the test case, I might as well post it. This code does NOT contain the glutMainLoop() I mentionned. I could do so if required, but Id need to also send you a makefile. When I figure out what is going on, I will let you know... If anyone has any ideas, please feel free to share! Thanks, Eric Test code..... /*****************************************************************************/ // main.cpp /*****************************************************************************/ #include <iostream> #include <string> #include <boost/graph/property_iter_range.hpp> #include <boost/graph/adjacency_list.hpp> #include <boost/graph/graph_traits.hpp> #include <boost/property_map.hpp> #include <boost/smart_ptr.hpp> using namespace std; using namespace boost; /*****************************************************************************/ // class CObject { protected: CObject(){}; protected: virtual ~CObject(){cout << "CObject cleanup" << endl;}; public: virtual void SetObjectName(const string& strName) = 0; virtual const std::string GetObjectName() = 0; }; // class C1 : public CObject { public: C1(){}; protected: virtual ~C1(){cout << "C1 cleanup" << endl;}; public: // Copy constructor C1(const C1& object) : CObject(object){}; }; class C2 : public C1 { public: C2(); C2(const string& strName) : m_strName(strName) {}; ~C2(){cout << "C2 cleanup" << endl;}; public: // Copy constructor C2(const C2& object) : C1(object), m_strName(object.m_strName) {}; // Data private: string m_strName; public: inline void SetObjectName(const string& strName) {m_strName = strName;}; inline const std::string GetObjectName() {return m_strName;}; }; // struct graph_node_t { enum { num = 1000 }; typedef boost::vertex_property_tag kind; }; struct Print { template<class T> Print& operator() (const T& t) { std::cout << t << endl; return (*this); } }; // class CTester { public: CTester() {}; ~CTester() {cout << "CTester cleanup" << endl;}; // Graph stuff private: typedef boost::property<boost::vertex_name_t, std::string> node_name_t; typedef boost::property<graph_node_t, boost::shared_ptr<CObject>, node_name_t> node_property_t; typedef boost::adjacency_list<listS, vecS, bidirectionalS, node_property_t> graph_t; typedef graph_traits<graph_t>::vertex_descriptor vertexdescriptor_t; graph_t m_Graph; // private: inline boost::shared_ptr<CObject> getNodeProperty(const vertexdescriptor_t& vertex) { boost::property_map<graph_t, graph_node_t>::type node_prop_map; node_prop_map = boost::get(graph_node_t(), m_Graph); return node_prop_map[vertex]; } boost::shared_ptr<CObject> getNodebyName(const std::string& strName) { boost::shared_ptr<CObject> node_prop; boost::graph_traits<graph_t>::vertex_iterator vi, vi_end; boost::tie(vi, vi_end) = boost::vertices(m_Graph); for(; vi != vi_end; ++vi) { node_prop = getNodeProperty(*vi); if(node_prop != 0) { if(node_prop->GetObjectName() == strName) break; } } return node_prop; } // public: template <typename T> void addObject(const T& object) { // Create a vertex boost::shared_ptr<T> spObject(new T(object)); // Add the vertex + its name to the graph boost::add_vertex(node_property_t(spObject, node_name_t(spObject->GetObjectName())), m_Graph); } template <typename T> boost::shared_ptr<T> getobject(const std::string& strName) { boost::shared_ptr<CObject> abc = getNodebyName(strName); shared_ptr<T> def = boost::dynamic_pointer_cast<T>(abc); return def; } void PrintObjects() { graph_property_iter_range<graph_t, vertex_name_t>::type test = get_property_iter_range(m_Graph, vertex_name_t()); cout << "Printing all vertices:" << endl; std::for_each(test.first, test.second, Print()); } }; /*****************************************************************************/ int main(int argc, char **argv) { CTester tester_class; tester_class.addObject(C2("class one")); tester_class.addObject(C2("class two")); boost::shared_ptr<C2> abc = tester_class.getobject<C2>("class one"); cout << abc->GetObjectName() << endl; return 0; } /*****************************************************************************/ Peter Dimov wrote:

Eric Damphousse wrote:
When I figure out what is going on, I will let you know... If anyone has any ideas, please feel free to share!
Only the obvious one that the glutMainLoop does a direct to system exit. Have you verified that it reaches back to main? -- -- Grafik - Don't Assume Anything -- Redshift Software, Inc. - http://redshift-software.com -- rrivera/acm.org - grafik/redshift-software.com - 102708583/icq
participants (3)
-
Eric Damphousse
-
Peter Dimov
-
Rene Rivera