
Hi There, I am using the Boost.MultiIndex and I am facing a problem that I am try to resolving (debbuging) already about 20 hours... I think I get the problem isolated, but I don't know how to solve, and I don't know if this it is implemented. So I decided to make a example, it is a little big, but I put it as resumed as I could and post here in order to know if anyone could help me out. I will try to explain briefly here, I will copy the main() code right under the explanation, but the whole code of the example is in the end of the e-mail (with the classes and functions) If you want you could try to run too see what is the problem that I am talking about.) When I try to access an pair of iterators pair<propIt,propIt> that I stored inside a class (propertystream_h), somehow is changing to where the iterator points, I think it could be because the object which has originate (Graph) the index is created, stored in in a static index (which I call _graphRep) from the DynamicGraphs, passed to a handler (Graph_h), and then after the Graph goes out of scope it is destroyed. When the Graph_h._localGraph (copy of the iterator->Graph returned by the insertion in the _graphRep) access its member _globalProperties (which is an index containing the fields: {string _key, string _value, propertystream_h _props} from the struct globalPropSchema) through a iterator (let's call it: gpit), then it is fine. But then when I try to access through the gpit->_props._propRangeIt.first, the iterator of the propertystream_h (_propRangeIt.first), then the iterators, some how are messed up. ( -> in this example it points to last element, and then when I get next, never finds the end(). (sometimes it return some trash, sometimes I get segmentation fault). So I would like to know why it is messing with the iterator? And how could I solve this problem? that's it, best regards, Rodrigo P.S.: I hope someone can help me... copy of the main(): int main(){ DynamicGraphs dg; Graph_h graph_h; propertystream_h propS; property_h prop_h; GlobalPropIterator gpit; GlobalProp_h gp_h; propertystream_h ps_h; property_h p_h; graph_h = dg.createGraph("COI:0351-123-4555"); if (!graph_h) cout << "Unsuccessful creation!"<<endl; else cout << "Successful creation!" <<endl; //It works, because it takes from the _localPropRep, and it passes it as value!!! ps_h = graph_h->lookupLocalProp("name"); while(!ps_h.end()){ cout << "LocalProperties: "; p_h=ps_h.next(); cout << "Key: " << p_h.key() << " Value: " << p_h.value() <<endl; } // It does not work, because is accessing the propertystream_h from // the _globalPropRep (index of the tuple // {string globalkey, string value, propertystream_h props} // the propertystream_h it has as member a pair of iterators for another index. // -> after a lot of debugging (about 16h) OI found out that // it seems that during the creation of a graph, // when it passes the graph to graph_h, and goes out of scope, it keep the // iterator reference to the first element, but just that... the next // gives me segmentation fault. Anyone knows how to pass the graph and the its members // the indexes-repositories as value, so it would not depend on the pointing to // the graph that was freed from the memory? gpit = graph_h->properties("*"); if (!gpit) cout << "Not found any property in the globalProperties Repository."<<endl; else{ int i=0; while (!gpit.end()) { gp_h = gpit.next(); cout << "While_1::Iteration_" << ++i << endl; cout << "GlobalProperty key: " << gp_h.key() << endl; cout << "GlobalProperty value: " << gp_h.value() << endl; ps_h = gp_h.propertyStreamHandler(); int j = 0; while (!ps_h.end()){ p_h = ps_h.next(); cout << "While_2::Iteration" << ++j << endl; cout << "GlobalProperty::PropertyStream: key " << p_h.key() << endl; cout << "GlobalProperty::PropertyStream: value " << p_h.value() << endl; } } } } Here it is the code: /* * IndexProblem.cpp * * Created on: Feb 6, 2009 * Author: rodrigo */ #include <boost/multi_index_container.hpp> #include <boost/multi_index/hashed_index.hpp> #include <boost/multi_index/member.hpp> #include <boost/multi_index/ordered_index.hpp> #include <boost/multi_index/composite_key.hpp> #include <boost/tuple/tuple.hpp> #include <boost/tokenizer.hpp> #include <boost/lambda/lambda.hpp> #include <climits> #include <iomanip> #include <iostream> #include <ctime> #include <string> #if !defined(NDEBUG) #define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING #define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE #endif using std::string; using std::pair; using std::ostream; using std::cout; using std::endl; using boost::multi_index_container; using namespace boost::multi_index; struct property { string _key; string _value; /// Default Constructor property(){} /// Constructor with parameters: initialize the name and graph property(string key, string value) : _key(key), _value(value) {} /// Copy Contructor property(const property &pm) : _key(pm._key), _value(pm._value) {} //For debugging TODO: delete later friend ostream& operator<<(ostream& os, const property &p){ os << "Key: " << p._key << " value: " << p._value << endl; return os; } }; /// Indexing in the data structure PropMap typedef multi_index_container< property, indexed_by< hashed_non_unique< BOOST_MULTI_INDEX_MEMBER(property, string, _key) > >
propIndex;
typedef propIndex::iterator propIt; class property_h { private: /// Access to properties through the iterator propIt _pit; public: /// Default Constructor property_h(){} /// Constructor with Parameters: for lookup of Nodes property_h (const propIt &it) : _pit(it){} /// Constructor with Parameters: for lookup of Nodes property_h (const property_h &h) : _pit(h._pit){} /// Returns the key from the property being handled string key() const {return _pit->_key;} /// Returns the value from the property being handled string value() const {return _pit->_value;} }; class propertystream_h { /// _propRangeIt: for keeping a range in order to iterate over the graphs pair<propIt,propIt> _propRangeIt; /// _noMatches: true if there are no matches during the lookup function bool _noMatches; public: /// Default Constructor propertystream_h() : _noMatches(true){} /// Constructor with parameters for local lookup propertystream_h(pair<propIt,propIt> rangeIt, bool noMatches) : _propRangeIt(rangeIt), _noMatches(noMatches){ } /// Default Constructor propertystream_h(const propertystream_h &ps) : _propRangeIt(ps._propRangeIt), _noMatches(ps._noMatches){} // returns null_h on end of stream ... property_h next(){ return property_h(_propRangeIt.first++); } /// This function returns true whenever is the end of the stream bool end(){ return (_propRangeIt.first == _propRangeIt.second); } /// Overload operator!: shows if a creation was unsuccessful bool operator!(){ return _noMatches; } }; struct globalPropSchema{ string _key; string _value; propertystream_h _props; /// Default Constructor globalPropSchema() : _key(""), _value(""), _props(){} /// Parameter Constructor globalPropSchema(string k, string value, propertystream_h props) : _key(k), _value(value), _props(props){} /// Copy Constructor globalPropSchema(const globalPropSchema &gps) : _key(gps._key), _value(gps._value), _props(gps._props){} //TODO: Delete it: Debug friend ostream& operator<<(ostream &os, const globalPropSchema &gps){ os << "Key: " << gps._key << " Value: "<< gps._value << " PropertyStreamAdress: " << &gps._props <<endl; return os; } }; typedef multi_index_container< globalPropSchema, indexed_by< ordered_non_unique< composite_key< globalPropSchema, BOOST_MULTI_INDEX_MEMBER(globalPropSchema, string, _key), BOOST_MULTI_INDEX_MEMBER(globalPropSchema, string, _value) >, composite_key_compare< std::greater<string>, std::less<string> > > >
grobalProperties;
/// Iterator for the data structure of the global properties index typedef grobalProperties::iterator globalPropIt; class GlobalProp_h{ private: /// Access to globalPropertiest items through the iterator globalPropIt _gpit; public: /// Default Constructor GlobalProp_h(){} /// Constructor with Parameters: for lookup of Nodes GlobalProp_h (const globalPropIt &it) : _gpit(it){} /// Copy Constructor GlobalProp_h (const GlobalProp_h &gph) : _gpit(gph._gpit){} /// Access to key of globalPropeties items string key(){ return _gpit->_key;} /// Access to value of globalPropeties items string value(){return _gpit->_value;} propertystream_h propertyStreamHandler(){ return _gpit->_props; } }; /// Iterator for the data structure of the global properties index typedef grobalProperties::iterator globalPropIt; class GlobalPropIterator{ private: /// _propRangeIt: for keeping a range in order to iterate over the graphs pair<globalPropIt,globalPropIt> _globalPropRangeIt; /// _noMatches: true if there are no matches during the lookup function bool _noMatches; public: /// Default Constructor GlobalPropIterator(){} /// Constructor with parameters for local lookup GlobalPropIterator(pair<globalPropIt,globalPropIt> rangeIt, bool noMatches) : _globalPropRangeIt(rangeIt), _noMatches(noMatches){} /// Default Constructor GlobalPropIterator(const GlobalPropIterator &gpi) : _globalPropRangeIt(gpi._globalPropRangeIt), _noMatches(gpi._noMatches){} // returns null_h on end of stream ... GlobalProp_h next(){ return GlobalProp_h(_globalPropRangeIt.first++); } /// This function returns true whenever is the end of the stream bool end(){ return (_globalPropRangeIt.first == _globalPropRangeIt.second); } /// Overload operator!: shows if a creation was unsuccessful bool operator!(){ return _noMatches; } }; class Graph { private: propIndex _localPropRep; /// Repository for the properties of the global properties related to the graph; grobalProperties _globalPropRep; public: // TODO: Really constructors /// Default Constructor Graph() {} /// Copy constructors Graph(const Graph &g) : _localPropRep(g._localPropRep), _globalPropRep(g._globalPropRep){} bool addProperty(string key, string value); GlobalPropIterator properties(string pattern) const; /// Function to lookup Local Properties propertystream_h lookupLocalProp(string pattern); friend class Graph_h; }; /// GraphMap: Data Structure for setting an index in the uniqueGraphName and retrieving handler Graph_h struct graphMap { string _name; Graph _graph; /// Default Constructor graphMap(){} /// Constructor with parameters: initialize the name and graph graphMap(string uniqueGraphName, Graph graph) : _name(uniqueGraphName), _graph (graph) {} /// Constructor with parameters: initialize the name and graph graphMap(const graphMap &gm) : _name(gm._name), _graph (gm._graph) {} }; ///ordered_unique Index in the data structure graph_hm typedef multi_index_container< graphMap, indexed_by< ordered_unique< BOOST_MULTI_INDEX_MEMBER(graphMap,string,_name) > >
graphIndex;
/// Defing an iterator for the graphMapIndex typedef graphIndex::iterator graphIt; class Graph_h { private: /// \brief GraphIterator: Iterator pointing to the Graph graphIt _git; Graph _localGraph; bool _createSuccess; public: /// Default Constructor Graph_h() : _createSuccess(false) {} /// Constructor with Parameters: for creation of Graphs Graph_h ( pair<graphIt,bool> creation) : _git(creation.first), _createSuccess(creation.second){ _localGraph = creation.first->_graph; } /// Constructor with Parameters: for lookup of Graphs Graph_h (const graphIt &it) : _git(it), _createSuccess(false){ _localGraph = it->_graph; } /// Constructor with Parameters: for lookup of Graphs Graph_h (const Graph_h &h) : _git(h._git), _localGraph(h._localGraph), _createSuccess(h._createSuccess){} bool operator!(){ return !_createSuccess; } /// Operator-> overloading: allows access to graph members Graph* operator->() {return &_localGraph;} }; propertystream_h Graph::lookupLocalProp(string pattern){ pair<propIt,propIt> rangeIt; propIt rangeItfirst = _localPropRep.find(pattern); rangeIt.first = rangeItfirst; rangeIt.second = _localPropRep.end(); if (rangeIt.first != _localPropRep.end()) // second parameter means that the variable noMatches, so false in case that found the key return propertystream_h(rangeIt, false); else //No matches return propertystream_h(rangeIt, true); } GlobalPropIterator Graph::properties(string pattern) const{ pair<globalPropIt,globalPropIt> globalRangePropIt; bool noMatchesTmp=false; //Whole range if (!pattern.compare("*")){ globalRangePropIt.first = _globalPropRep.begin(); globalRangePropIt.second = _globalPropRep.end(); } if (globalRangePropIt.first == globalRangePropIt.second) noMatchesTmp = true; return GlobalPropIterator(globalRangePropIt, noMatchesTmp); } bool Graph::addProperty(string key, string value){ bool boolLocal, boolGlobal; pair <propIt,propIt> rangePropIt; string globalKey = "graph:"; globalKey.append(key); // "graph:namePorperty" boolLocal = _localPropRep.insert(property(key,value)).second; //Defining the whole range for iterate over the local properties rangePropIt.first = _localPropRep.begin(); rangePropIt.second = _localPropRep.end(); //Debug propIt it = rangePropIt.first; cout << "How it should be showed when accessing the iterator..."<<endl; while (rangePropIt.first != rangePropIt.second){ cout << "DEBUG@addProperty: " << *(rangePropIt.first++); } cout << endl; rangePropIt.first = it; //Debug boolGlobal = _globalPropRep.insert( globalPropSchema( globalKey, value, propertystream_h(rangePropIt, false) ) ).second; return (boolLocal && boolGlobal); } class DynamicGraphs { public: /// Data member to represent the graph repository (using ordered_unique index) static graphIndex _graphRep; Graph_h createGraph(string uniqueGraphName); }; graphIndex DynamicGraphs::_graphRep; /// Creation of Graph in DynamicGraphs Graph_h DynamicGraphs::createGraph(string uniqueGraphName){ Graph g; g.addProperty("name", uniqueGraphName); //Test g.addProperty("age", "Unknown"); g.addProperty("color", "blue"); return Graph_h( _graphRep.insert( graphMap( uniqueGraphName, g ) ) ); } int main(){ DynamicGraphs dg; Graph_h graph_h; propertystream_h propS; property_h prop_h; GlobalPropIterator gpit; GlobalProp_h gp_h; propertystream_h ps_h; property_h p_h; graph_h = dg.createGraph("COI:0351-123-4555"); if (!graph_h) cout << "Unsuccessful creation!"<<endl; else cout << "Successful creation!" <<endl; //It works, because it takes from the _localPropRep, and it passes it as value!!! ps_h = graph_h->lookupLocalProp("name"); while(!ps_h.end()){ cout << "LocalProperties: "; p_h=ps_h.next(); cout << "Key: " << p_h.key() << " Value: " << p_h.value() <<endl; } // It does not work, because is accessing the propertystream_h from // the _globalPropRep (index of the tuple // {string globalkey, string value, propertystream_h props} // the propertystream_h it has as member a pair of iterators for another index. // -> after a lot of debugging (about 16h) OI found out that // it seems that during the creation of a graph, // when it passes the graph to graph_h, and goes out of scope, it keep the // iterator reference to the first element, but just that... the next // gives me segmentation fault. Anyone knows how to pass the graph and the its members // the indexes-repositories as value, so it would not depend on the pointing to // the graph that was freed from the memory? gpit = graph_h->properties("*"); if (!gpit) cout << "Not found any property in the globalProperties Repository."<<endl; else{ int i=0; while (!gpit.end()) { gp_h = gpit.next(); cout << "While_1::Iteration_" << ++i << endl; cout << "GlobalProperty key: " << gp_h.key() << endl; cout << "GlobalProperty value: " << gp_h.value() << endl; ps_h = gp_h.propertyStreamHandler(); int j = 0; while (!ps_h.end()){ p_h = ps_h.next(); cout << "While_2::Iteration" << ++j << endl; cout << "GlobalProperty::PropertyStream: key " << p_h.key() << endl; cout << "GlobalProperty::PropertyStream: value " << p_h.value() << endl; } } } } -- ************************************************* Rodrigo Dias Ferreira Master Student of Computational Engineering Technische Universität Dresden - Germany Mobile Phone:+49 171 3158797 E-mail: rodrigodias@gmx.de ************************************************* Jetzt 1 Monat kostenlos! GMX FreeDSL - Telefonanschluss + DSL für nur 17,95 Euro/mtl.!* http://dsl.gmx.de/?ac=OM.AD.PD003K11308T4569a