Boost C++ Libraries: Ticket #4044: reset_object_address with library-created objects https://svn.boost.org/trac10/ticket/4044 <p> The archive reset_object_address method does not work for objects created by the serialization library. </p> <p> This appears to be the issue as discussed here: <a class="ext-link" href="http://lists.boost.org/boost-users/2008/11/42417.php"><span class="icon">​</span>http://lists.boost.org/boost-users/2008/11/42417.php</a> It looks like the issue was never addressed. </p> <p> The code below demonstrates. Is this considered to be the desired behaviour? </p> <p> I would've thought the object tracking should be applicable, regardless of how the object is constructed. </p> <pre class="wiki">#include &lt;boost/archive/text_oarchive.hpp&gt; #include &lt;boost/archive/text_iarchive.hpp&gt; #include &lt;boost/serialization/serialization.hpp&gt; #include &lt;sstream&gt; struct Ob { Ob() : m_(1) {} int m_; template &lt;typename A&gt; void serialize(A &amp;a, const unsigned) { a &amp; m_; } }; int main(int, char *[]) { std::string serText; { std::ostringstream str; boost::archive::text_oarchive oa(str); Ob *p = new Ob; oa &amp; p &amp; 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 &amp; 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 &amp; p; assert(p == newp); // Traps delete newp; } return 0; } </pre> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/4044 Trac 1.4.3 Robert Ramey Fri, 26 Mar 2010 17:09:26 GMT <link>https://svn.boost.org/trac10/ticket/4044#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4044#comment:1</guid> <description> <p> 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. </p> <pre class="wiki">int main(int, char *[]) { std::string serText; { std::ostringstream str; boost::archive::text_oarchive oa(str); Ob *p = new Ob; Ob *p2 = p; oa &amp; p &amp; p2; // 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; Ob *p2 = 0; ia &amp; p &amp; p2; delete p; } return 0; } </pre><p> Robert Ramey </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Richard Hazlewood</dc:creator> <pubDate>Fri, 26 Mar 2010 23:10:03 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/4044#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4044#comment:2</guid> <description> <p> 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 ;-) ): </p> <pre class="wiki">class Whatever { typedef boost::function&lt;Signature&gt; Func; Func m_func; /// template &lt;typename A&gt; void serialize(A &amp;a, const unsigned) { if (A::is_saving::value) { FunctionObject *p = m_func.target&lt;FunctionObject&gt;(); // Let's serialize the function object via pointer a &amp; p; } else { FunctionObject *p = 0; a &amp; p; m_func = *p; // Hand function object to boost::function FunctionObject *realp = m_func.target&lt;FunctionObject&gt;(); 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) } } }; </pre><p> Also, I can't do: </p> <pre class="wiki"> { a &amp; *m_func.target&lt;FunctionObject&gt;(); } else { m_func = FunctionObject(); // Initialize boost::function with empty object FunctionObject *realp = m_func.target&lt;FunctionObject&gt;(); a &amp; *realp; // Deserialize right in } </pre><p> Because the <code>FunctionObject</code> has a private default ctor. This is why I was trying to route it through the serialization library's pointer creation (<code>FunctionObject</code> has <em>access</em> friendship). </p> <p> Further, this is a simplification. In the real code <code>FunctionObject</code> is a template argument, but it <em>is</em> serializable. </p> <p> Hope this is clearer. Best... </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Robert Ramey</dc:creator> <pubDate>Fri, 26 Mar 2010 23:31:19 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/4044#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4044#comment:3</guid> <description> <p> I'm still not getting it. Doesn't this work? </p> <pre class="wiki">template&lt;class Archive&gt; void serialize(Archive &amp;ar, boost::function&lt;Signature&gt; &amp; f, const unsigned int version){ // ar &amp; any member variables here. } class Whatever { typedef boost::function&lt;Signature&gt; Func; Func m_func; /// template &lt;typename A&gt; void serialize(A &amp;a, const unsigned) { a &amp; m_func; } }; </pre><p> 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. </p> <p> Robert Ramey </p> </description> <category>Ticket</category> </item> <item> <dc:creator>anonymous</dc:creator> <pubDate>Fri, 26 Mar 2010 23:49:21 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/4044#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4044#comment:4</guid> <description> <p> Well, it would work if you can tell me what goes in here: </p> <pre class="wiki">template&lt;class Archive&gt; void serialize(Archive &amp;ar, boost::function&lt;Signature&gt; &amp; f, const unsigned int version){ // ** here ** } </pre><p> 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. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Robert Ramey</dc:creator> <pubDate>Sat, 27 Mar 2010 03:46:45 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/4044#comment:5 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4044#comment:5</guid> <description> <p> What I think you want is a variable functor. This has nothing to do with seriaization but I'll address it anyway. </p> <p> a) Method one. </p> <blockquote> <p> 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 </p> </blockquote> <p> b) Method two. </p> <blockquote> <p> 1) Use a boost::variant which can hold any one of all the types of functors you want </p> <blockquote> <p> to use. </p> </blockquote> <p> 2) serialize an instance of the variant. This is already in the library. </p> </blockquote> <p> 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. </p> <p> This is the best I can guess as to what you want to do give the information I have. </p> <p> Robert Ramey </p> <p> all the functor derived from a common base class </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Richard Hazlewood</dc:creator> <pubDate>Sat, 27 Mar 2010 09:19:13 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/4044#comment:6 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4044#comment:6</guid> <description> <p> 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). </p> <p> The boost::function approach has a convenience (and elegance, IMO) for the application I am working on. </p> <p> 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&lt;&gt; friend: </p> <pre class="wiki">template&lt;class Archive&gt; void serialize(Archive &amp;ar, boost::function&lt;Signature&gt; &amp; f, const unsigned int version){ if (Archive::is_saving:value) { ar &amp; *f.target&lt;MyFunctor&gt;(); } else { // get memory space for functor auto_ptr_thing&lt;MyFunctor&gt; p = (MyFunctor*)new char[sizeof(MyFunctor)]; // in-place construct through the friend serialization::access::construct&lt;MyFunctor&gt;(&amp;p); // de-serialize ar &amp; *p; // hand over (this does incur a copy) f = *p.get(); // let p destruct, taking the memory with it } } </pre><p> 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 <em>cleaner</em>), 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. </p> <p> 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. </p> <p> Thank you for taking the time to discuss this. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Robert Ramey</dc:creator> <pubDate>Sat, 27 Mar 2010 15:56:27 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/4044#comment:7 https://svn.boost.org/trac10/ticket/4044#comment:7 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">invalid</span> </li> </ul> <p> 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. </p> <p> 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. </p> <p> Sorry I couldn't be more help. </p> <p> Robert Ramey </p> Ticket