Home > Back-end >  Store iterator inside a struct
Store iterator inside a struct

Time:06-30

I need to read data from multiple JSON files. The actual reading of data is performed later in the code, after some initialization stuffs. For reasons beyond the scope of this question, I believe that it would beneficial for my application to store somewhere an iterator set to the first element of each JSON file. In this way, I would be able to iterate over each JSON file and read the i-th element from each of them, at later time.

The issue: if I create the iterator and use it to parse data right away everything works. If I create the iterator, store it inside a struct and use later on, I get a read access violation.

Following are some pieces of code to better explain my issue. First of all, here is a partial declaration of the structure holding info about a single JSON file:

typedef struct _struct
{
  ...
  boost::property_tree::ptree json_struct;
  boost::property_tree::ptree::iterator it;
  ...
} json_handler;

Just FYI, later on, I declare a container for holding multiple handlers:

std::map<std::string, json_handler> mjh;

The following works:

json_handler cms;
boost::property_tree::read_json(full_path, cms.json_struct);
boost::property_tree::ptree &data = cms.json_struct.get_child("frames");
// current_msg.it = data.begin();

// If I do iterate over the json content here, everything works.
for (boost::property_tree::ptree::iterator element = data.begin(); element != data.end(); element  )
  double time = element->second.get<double>("ST");

// The following line just inserts the current json_handler inside the map
mjh.insert(std::pair<std::string,json_handler>(name, cms));

The following does not work:

... This is later in the code when it's time to use the data

std::map<std::string, json_handler>::iterator it;

for (it = mjh.begin(); it != mjh.end(); it  )
{
  double _st = it->second.it->second.get<double>("ST");
  std::cout << "ST: " << std::to_string(_st ) << std::endl;
  ...
}

The question: can I store an iterator inside a struct. If no, why?

CodePudding user response:

You're storing iterators, but using them after they were invalidated.

Reasons for invalidation are when the corresponding ptree node moved, was erased or destructed.

Just store the ptree inside the struct, which makes sure the ptree's lifetime extends long enough. Of course, you will still need to make sure the node pointed to by the iterator is not erased from the ptree.

On a side note, don't use Property Tree for JSON parsing. It has serious limitations. Use Boost JSON instead: https://www.boost.org/doc/libs/1_79_0/libs/json/doc/html/index.html

It understands JSON correctly, is much faster and has a more user-friendly interface.

  • Related