Boost logo

Boost Users :

Subject: [Boost-users] Problem with Iterator passing inside an index... a little complex...
From: Rodrigo Dias Ferreira (rodrigodias_at_[hidden])
Date: 2009-02-06 10:09:27


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_at_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_at_[hidden]
*************************************************
Jetzt 1 Monat kostenlos! GMX FreeDSL - Telefonanschluss + DSL 
für nur 17,95 Euro/mtl.!* http://dsl.gmx.de/?ac=OM.AD.PD003K11308T4569a

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