Opened 13 years ago
Closed 13 years ago
#4044 closed Bugs (invalid)
reset_object_address with library-created objects
Reported by: | Richard Hazlewood | Owned by: | Robert Ramey |
---|---|---|---|
Milestone: | Boost 1.43.0 | Component: | serialization |
Version: | Boost 1.42.0 | Severity: | Problem |
Keywords: | reset_object_address heap allocated | Cc: |
Description
The archive reset_object_address method does not work for objects created by the serialization library.
This appears to be the issue as discussed here: http://lists.boost.org/boost-users/2008/11/42417.php It looks like the issue was never addressed.
The code below demonstrates. Is this considered to be the desired behaviour?
I would've thought the object tracking should be applicable, regardless of how the object is constructed.
#include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_iarchive.hpp> #include <boost/serialization/serialization.hpp> #include <sstream> struct Ob { Ob() : m_(1) {} int m_; template <typename A> void serialize(A &a, const unsigned) { a & m_; } }; int main(int, char *[]) { std::string serText; { std::ostringstream str; boost::archive::text_oarchive oa(str); Ob *p = new Ob; oa & p & p; // Serialize two instances; serialization lib will track second delete p; serText = str.str(); } { std::istringstream str(serText); boost::archive::text_iarchive ia(str); Ob *p = 0; ia & p; Ob *newp = new Ob(*p); ia.reset_object_address(newp, p); // newp should now be used for future p uses delete p; p = 0; // Let's explicitly get shot of this ia & p; assert(p == newp); // Traps delete newp; } return 0; }
Change History (7)
comment:1 by , 13 years ago
comment:2 by , 13 years ago
Okay, I was trying to generalize/test-case. Here's something closer to what I'm really doing (I'm away from the real code, so this is from memory ;-) ):
class Whatever { typedef boost::function<Signature> Func; Func m_func; /// template <typename A> void serialize(A &a, const unsigned) { if (A::is_saving::value) { FunctionObject *p = m_func.target<FunctionObject>(); // Let's serialize the function object via pointer a & p; } else { FunctionObject *p = 0; a & p; m_func = *p; // Hand function object to boost::function FunctionObject *realp = m_func.target<FunctionObject>(); a.reset_object_address(realp, p); // Does not work delete p; // Hence this will ultimately mess things up // (subsequent serialization may land in same address) } } };
Also, I can't do:
{ a & *m_func.target<FunctionObject>(); } else { m_func = FunctionObject(); // Initialize boost::function with empty object FunctionObject *realp = m_func.target<FunctionObject>(); a & *realp; // Deserialize right in }
Because the FunctionObject
has a private default ctor. This is why I was trying to route it through the serialization library's pointer creation (FunctionObject
has access friendship).
Further, this is a simplification. In the real code FunctionObject
is a template argument, but it is serializable.
Hope this is clearer. Best...
comment:3 by , 13 years ago
I'm still not getting it. Doesn't this work?
template<class Archive> void serialize(Archive &ar, boost::function<Signature> & f, const unsigned int version){ // ar & any member variables here. } class Whatever { typedef boost::function<Signature> Func; Func m_func; /// template <typename A> void serialize(A &a, const unsigned) { a & m_func; } };
reset_object_address has only turned out to be necessary in the most rarest of cases. If you think you really need it, you might be missing something simpler.
Robert Ramey
comment:4 by , 13 years ago
Well, it would work if you can tell me what goes in here:
template<class Archive> void serialize(Archive &ar, boost::function<Signature> & f, const unsigned int version){ // ** here ** }
This just moves the problem to another function. It is the actual serialization of the functor, being held by boost::function, that I'm trying to achieve.
comment:5 by , 13 years ago
What I think you want is a variable functor. This has nothing to do with seriaization but I'll address it anyway.
a) Method one.
1) Derive all functors from a common base class. 2) Make the base class virtual by adding one virtual function 3) Good idea to make it abstract as well. 4) maybe you want to make operator()() virtual as well. 4) serialize as one would any base class pointer - using EXPORT or register_type
b) Method two.
1) Use a boost::variant which can hold any one of all the types of functors you want
to use.
2) serialize an instance of the variant. This is already in the library.
The crux of the issue is that you really want to to serialize a type rather than a piece of data. Either of the above two methods will do the job.
This is the best I can guess as to what you want to do give the information I have.
Robert Ramey
all the functor derived from a common base class
comment:6 by , 13 years ago
I've certainly considered method-1, as you outline above. Method-2 is an alternative I had not considered. However, both would require large resstructuring of the code-base (which may be inevitable).
The boost::function approach has a convenience (and elegance, IMO) for the application I am working on.
It is only access to the default ctor of the function object that is getting in the way. For example, I could copy the behaviour of the serialization library's auto_ptr_with_deleter just to get to serialization::access::construct<> friend:
template<class Archive> void serialize(Archive &ar, boost::function<Signature> & f, const unsigned int version){ if (Archive::is_saving:value) { ar & *f.target<MyFunctor>(); } else { // get memory space for functor auto_ptr_thing<MyFunctor> p = (MyFunctor*)new char[sizeof(MyFunctor)]; // in-place construct through the friend serialization::access::construct<MyFunctor>(&p); // de-serialize ar & *p; // hand over (this does incur a copy) f = *p.get(); // let p destruct, taking the memory with it } }
This avoids the object tracking. I was just trying to avoid duplicating this inner-library behaviour by routing through its pointer serialization (and it would be cleaner), but, the point of this trac, as soon as I do that I have to worry about tracking - and reset_object_address did not do what I expected.
Ultimately, if the current library behaviour of reset_object_address is considered correct (or not appliable to this type of heap allocated object), then I will consider the alternatives.
Thank you for taking the time to discuss this.
comment:7 by , 13 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
What you're trying to do is make a variable functor. This is not a serialization issue. There are several ways to do it - none of which has any problem with serialization.
So, I've done what I can. I'm going to mark this ticket "wont fix". What I really mean is "Can't fix" but the dropdown list doesn't give me that option.
Sorry I couldn't be more help.
Robert Ramey
It's very hard to discern what you're actually trying to do here. But since, I've come this far I'll ask what you think of the following example - derived from yours.
Robert Ramey