views:

93

answers:

2

Boost deserialization of contained object fails when performed from a constructor, but succeeds otherwise.

E.G.:

ContainingClass::ContainingClass() {
    pNA = new objectArray*[NUMBER]; // allocates ptrs
    // ...
    pNA[ii] = new objectArray(SIZE);// allocates object array, and object array
                                    // has a std::map "PatternsMap"
    // ...

    pNA[ii]->load(pNA[ii], "../release/NA Data/NAData_a description_NA0"); //fails
    pNA[ii]->PatternsMap.size(); //size = 0
}

If I call the following lines of code after the constructor exits then all is well:

pNA[ii]->load(pNA[ii], "../release/NA Data/NAData_a description_NA0"); //succeeds
pNA[ii]->PatternsMap.size();//size > 0

Any ideas? Note, that in the constructor example I verified that objectArray was constructed first.

A: 

Prefer to use a std::vector or a Boost.Array instead of a plain array, you'll have less memory issues... and they actually default construct the objects they hold so it will save some lines of code.

I suppose that load is a method of objectArray, and I wonder why you actually call it like that:

pNA[ii]->load(pNA[ii], "../release/NA Data/NAData_a description_NA0");

I mean, when using a method, you already have an implicit parameter (this) that refer to the object, no need really to pass it twice (once as implicit and once as explicit).

Now of course, if we could have a look at the load method, that would be helpful. It is quite difficult to diagnose a problem of type:

My method foo fails, do you know why ?

The more precise YOU are, the more likely someone is to actually pinpoint your problem exactly.

Matthieu M.
A: 

To: Stjepan Rajko: The ContainingClass is dynamically created at run-time.

To Matthieu M: It seems that the Boost authors may have gotten stuck in "a global initialization fiasco".

Per the comment about std::vector, I use plain arrays because the code is highly parallel and I'm anticipating moving some of it to NVidia's CUDA. CUDA currently does not support C++, only C. In addition, (though less a factor) I feel quite at ease working with dynamic arrays and explicitly releasing the memory after... plus performance is a big priority. I've used std::vector and smart/auto ptrs in the places that I thought appropriate.

Per the comment about the implicit this, yes you are likely correct...I'm not sure what I was thinking when I made it explicit. Here is the serialize code that is in the objectArray class:

template[class Archive]//note the brakets had to be changed for this post

void serialize(Archive & ar, const unsigned int version) {

// only save/load A_name for newer archives

//if(version > 0)

// ar & A_name;

ar & PatternsMap;

}

void store(objectArray s, const char filename) {

// create and open a character archive for output
std::ofstream ofs(filename);
boost::archive::text_oarchive oa(ofs);
// write class instance to archive
oa << s;
// archive and stream closed when destructors are called

}

void load(objectArray s, const char filename) {

std::ifstream ifs(filename);
boost::archive::text_iarchive ia(ifs);
// read class state from archive
ia >> s;
// archive and stream closed when destructors are called

}

bhartsb
John Zwinck