undefined reference to base_object
I am working with the boost 1.40.0 serialization library and I am having trouble with class registration for polymorphic types. The code I have has worked fine with VS2005 and VS2008 for a long time; however, in linux with gcc (4.4.1-4ubuntu9), I am having issues. I am using the non-intrusive serialization method on a class that resides in a shared object file. I have simplified this down to where the serialization of the object is performed in an executable linking in the shared object file. In Windows I am registering the classes with boost using BOOST_CLASS_EXPORT_GUID. However, in linux, if I register the classes using this macro, the code compiles but does not link and gives an error similar to below for : testConfig.o: In function `boost::archive::detail::iserializer<boost::archive::text_iarchive, MyNamespace::MyDerivedClass>::load_object_data(boost::archive::detail::basic_iarchive&, void*, unsigned int) const': testConfig.cpp:(.text._ZNK5boost7archive6detail11iserializerINS0_13text_iarchiveEN7MoreOfMyClassRelatredDataEE16load_object_dataERNS1_14basic_iarchiveEPvj[boost::archive::detail::iserializer<boost::archive::text_iarchive, MyNamespace::MyDerivedClass>::load_object_data(boost::archive::detail::basic_iarchive&, void*, unsigned int) const]+0x96): undefined reference to `MyNamespace::MyBaseClass& boost::serialization::base_object<MyNamespace::MyBaseClass, MyNamespace::MyDerivedClass>(MyNamespace::MyDerivedClass const&)' The same error also occurs with save_object_data. If I don't register, my test fails with the unregistered class exception. I have tried placing the macros in both a header and a source file and I still get the linker errors following advice from here: http://www.boost.org/doc/libs/1_40_0/libs/serialization/doc/special.html#exp.... I also tried explicitly instantiating the base_object methods, but get an error indicating no matching definition exists, so I am assuming this is related to the issue - I'm just not sure how else to define the function. I am familiar with basic templating, but the serialization library source is beyond me. Any help would be greatly appreciated..... Thanks - John -- View this message in context: http://old.nabble.com/undefined-reference-to-base_object-tp28417529p28417529... Sent from the Boost - Users mailing list archive at Nabble.com.
John C wrote:
I am working with the boost 1.40.0 serialization library and I am having trouble with class registration for polymorphic types. The code I have has worked fine with VS2005 and VS2008 for a long time; however, in linux with gcc (4.4.1-4ubuntu9), I am having issues.
I am using the non-intrusive serialization method on a class that resides in a shared object file. I have simplified this down to where the serialization of the object is performed in an executable linking in the shared object file. In Windows I am registering the classes with boost using BOOST_CLASS_EXPORT_GUID. However, in linux, if I register the classes using this macro, the code compiles but does not link and gives an error similar to below for :
testConfig.o: In function `boost::archive::detail::iserializer<boost::archive::text_iarchive, MyNamespace::MyDerivedClass>::load_object_data(boost::archive::detail::basic_iarchive&, void*, unsigned int) const': testConfig.cpp:(.text._ZNK5boost7archive6detail11iserializerINS0_13text_iarchiveEN7MoreOfMyClassRelatredDataEE16load_object_dataERNS1_14basic_iarchiveEPvj[boost::archive::detail::iserializer<boost::archive::text_iarchive, MyNamespace::MyDerivedClass>::load_object_data(boost::archive::detail::basic_iarchive&, void*, unsigned int) const]+0x96): undefined reference to `MyNamespace::MyBaseClass& boost::serialization::base_object<MyNamespace::MyBaseClass, MyNamespace::MyDerivedClass>(MyNamespace::MyDerivedClass const&)'
The same error also occurs with save_object_data.
without seeing more, the only thing that occurs to me is to check that your non-instrusive save/load functions are in the correct namespace. Robert Ramey
If I don't register, my test fails with the unregistered class exception. I have tried placing the macros in both a header and a source file and I still get the linker errors following advice from here: http://www.boost.org/doc/libs/1_40_0/libs/serialization/doc/special.html#exp.... I also tried explicitly instantiating the base_object methods, but get an error indicating no matching definition exists, so I am assuming this is related to the issue - I'm just not sure how else to define the function. I am familiar with basic templating, but the serialization library source is beyond me.
Any help would be greatly appreciated.....
Thanks - John
Robert, Thanks for the quick response. This may be part of my confusion, and since visual studio is so screwy with how it lets certain things go that often won't even compile with gcc. Anyway, I have a shared library that doesn't use the serialization portion of the code, and can't have boost as a dependency, so we have a forward declaration that allows compilation. Header file: forward declaration: namespace boost { namespace serialization { class access; template<class Base, class Derived> Base& base_object(const Derived &d); } } In the private portion of the derived class declaration I have basically the following: friend class boost::serialization::access; template<class Archive> void serialize(Archive & ar, const unsigned int version) { ar & boost::serialization::base_object<MyBaseClass, MyDerivedClass>(*this); ar & mMember; } The base class is similar, minus of course the base_object call. The real library that uses the serialization code is in a static library that is included by a couple other shared libraries. When I upgraded to VS2008 (and boost 1.40.0) last year, I had some problems (in Windows) with unregistered classes. I found information (in the link in my post) that led me to move my export macros to a source file. I ended up also having to include the source file in each of the dependent shared libraries to get it to work. I never really did fully understand why that made it work, but I assumed it had something to do with the code being in a static library. Fast forward to now (linux), I have tried including that source file directly (and through the static library) in an executable that is a test runner to verify the serialization code is working, and this is where I am stuck. Hopefully that gives you enough information to better understand my problem. I appreciate you taking the time to answer my question. Robert Ramey wrote:
John C wrote:
I am working with the boost 1.40.0 serialization library and I am having trouble with class registration for polymorphic types. The code I have has worked fine with VS2005 and VS2008 for a long time; however, in linux with gcc (4.4.1-4ubuntu9), I am having issues.
I am using the non-intrusive serialization method on a class that resides in a shared object file. I have simplified this down to where the serialization of the object is performed in an executable linking in the shared object file. In Windows I am registering the classes with boost using BOOST_CLASS_EXPORT_GUID. However, in linux, if I register the classes using this macro, the code compiles but does not link and gives an error similar to below for :
testConfig.o: In function `boost::archive::detail::iserializer<boost::archive::text_iarchive, MyNamespace::MyDerivedClass>::load_object_data(boost::archive::detail::basic_iarchive&, void*, unsigned int) const': testConfig.cpp:(.text._ZNK5boost7archive6detail11iserializerINS0_13text_iarchiveEN7MoreOfMyClassRelatredDataEE16load_object_dataERNS1_14basic_iarchiveEPvj[boost::archive::detail::iserializer<boost::archive::text_iarchive, MyNamespace::MyDerivedClass>::load_object_data(boost::archive::detail::basic_iarchive&, void*, unsigned int) const]+0x96): undefined reference to `MyNamespace::MyBaseClass& boost::serialization::base_object<MyNamespace::MyBaseClass, MyNamespace::MyDerivedClass>(MyNamespace::MyDerivedClass const&)'
The same error also occurs with save_object_data.
without seeing more, the only thing that occurs to me is to check that your non-instrusive save/load functions are in the correct namespace.
Robert Ramey
If I don't register, my test fails with the unregistered class exception. I have tried placing the macros in both a header and a source file and I still get the linker errors following advice from here: http://www.boost.org/doc/libs/1_40_0/libs/serialization/doc/special.html#exp.... I also tried explicitly instantiating the base_object methods, but get an error indicating no matching definition exists, so I am assuming this is related to the issue - I'm just not sure how else to define the function. I am familiar with basic templating, but the serialization library source is beyond me.
Any help would be greatly appreciated.....
Thanks - John
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
-- View this message in context: http://old.nabble.com/undefined-reference-to-base_object-tp28417529p28427706... Sent from the Boost - Users mailing list archive at Nabble.com.
I would recommend you look at the1.42 documentation. This resolves a lot of the confusion about the usage of serialization in DLLS (aka shared libraries). The real problem is that when I made the library I didn't really consider all the implications of spreading the code accross DLLS and when I did, some many issues came up it took a while to get it right. I think it's correct now. One more iteration and it will be more bullet proof. Robert Ramey
I was hoping to avoid upgrading, but in case anyone else ever looks at this, here is what I did to get it working. My original code was for the serialization library included with boost 1.36.0 (I think). It continued working in Windows with a few minor tweaks (through several boost upgrades) until I tried to build in linux. As it turns out, somewhere along the line the call to serialize a base object from a derived object changed from this: template<class Archive> void serialize(Archive & ar, const unsigned int version) { ar & base_object<MyBaseClass, MyDerivedClass>(*this); .... } to this: template<class Archive> void serialize(Archive & ar, const unsigned int version) { ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(MyBaseClass); .... } I think this was the main cause of my problem, and this alone might make it work in boost 1.40.0. Since the header file that uses this is in a shared object file that in some cases cannot have any boost dependencies, I had a forward declaration for base_object. I had to remove the forward declaration and #def in the inclusion of the boost export.hpp header for the BOOST_SERIALIZATION_BASE_OBJECT_NVP macro. For boost 1.42.0 I also had to add the BOOST_CLASS_EXPORT_KEY and BOOST_CLASS_TYPE_INFO macros to the header and the BOOST_CLASS_EXPORT_IMPLEMENT to the source files (and of course get rid of the BOOST_CLASS_EXPORT (or BOOST_CLASS_EXPORT_GUID depending on what you are using). See the test files in the boost_1_42_0/libs/serialization/test for details. The moral of the story: If you are upgrading boost versions, don't assume the serialization library hasn't changed drastically, especially if you are serializing polymorphic types and even if it works fine in Windows. Thanks for the help Robert.... Robert Ramey wrote:
I would recommend you look at the1.42 documentation. This resolves a lot of the confusion about the usage of serialization in DLLS (aka shared libraries). The real problem is that when I made the library I didn't really consider all the implications of spreading the code accross DLLS and when I did, some many issues came up it took a while to get it right. I think it's correct now. One more iteration and it will be more bullet proof.
Robert Ramey
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
-- View this message in context: http://old.nabble.com/undefined-reference-to-base_object-tp28417529p28436304... Sent from the Boost - Users mailing list archive at Nabble.com.
John C wrote:
I think this was the main cause of my problem, and this alone might make it work in boost 1.40.0. Since the header file that uses this is in a shared object file that in some cases cannot have any boost dependencies, I had a forward declaration for base_object. I had to remove the forward declaration and #def in the inclusion of the boost export.hpp header for the BOOST_SERIALIZATION_BASE_OBJECT_NVP macro.
It's hard for me to guess what's going to happen if you start messing with the header - especiallly if you only reveal this after the fact. In order to limit dependencies, I would suggest a different technique. Don't use inline definiition. Use the following in your class declaration: template<class Archive> void serialization(Archive & ar, const unsigned int version); In a *.cpp file define the template and explicitly instantiate it for the archive types that you use. This will permit you to confine the inclusion of serialization library headers to a smaller set of files. When using serialization code (or any template code) with DLLS this technique will also address another problem which is starting to come up - Multiple (and potentially conflicting) template instantiations. This could lead to hellish debug scenarios as well as code bloat. In some cases the library can now detect this problem, but I had to suppress the trap because it broke too much user code. (That is, it detected too many problems in user code.) When I have nothing else to do, I plan to revisit this and provide a trap that the user will be able to explicitly override. It might not help, but at least the user won't be able to say he wasn't warned.
The moral of the story: If you are upgrading boost versions, don't assume the serialization library hasn't changed drastically, especially if you are serializing polymorphic types and even if it works fine in Windows.
Well, the changes didn't seem drastic to me. I think that is an overly harsh and missleading characterisation.
Thanks for the help Robert....
Your welcome. Robert Ramey
Yeah, sorry, I suppose that sounds worse than what I intended. I guess what I really mean is don't assume updates are backwards compatible... Robert Ramey wrote:
John C wrote:
I think this was the main cause of my problem, and this alone might make it work in boost 1.40.0. Since the header file that uses this is in a shared object file that in some cases cannot have any boost dependencies, I had a forward declaration for base_object. I had to remove the forward declaration and #def in the inclusion of the boost export.hpp header for the BOOST_SERIALIZATION_BASE_OBJECT_NVP macro.
It's hard for me to guess what's going to happen if you start messing with the header - especiallly if you only reveal this after the fact.
In order to limit dependencies, I would suggest a different technique. Don't use inline definiition. Use the following in your class declaration:
template<class Archive> void serialization(Archive & ar, const unsigned int version);
In a *.cpp file define the template and explicitly instantiate it for the archive types that you use. This will permit you to confine the inclusion of serialization library headers to a smaller set of files.
When using serialization code (or any template code) with DLLS this technique will also address another problem which is starting to come up - Multiple (and potentially conflicting) template instantiations. This could lead to hellish debug scenarios as well as code bloat. In some cases the library can now detect this problem, but I had to suppress the trap because it broke too much user code. (That is, it detected too many problems in user code.) When I have nothing else to do, I plan to revisit this and provide a trap that the user will be able to explicitly override. It might not help, but at least the user won't be able to say he wasn't warned.
The moral of the story: If you are upgrading boost versions, don't assume the serialization library hasn't changed drastically, especially if you are serializing polymorphic types and even if it works fine in Windows.
Well, the changes didn't seem drastic to me. I think that is an overly harsh and missleading characterisation.
Thanks for the help Robert....
Your welcome.
Robert Ramey
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
-- View this message in context: http://old.nabble.com/undefined-reference-to-base_object-tp28417529p28436618... Sent from the Boost - Users mailing list archive at Nabble.com.
John C wrote:
Yeah, sorry, I suppose that sounds worse than what I intended. I guess what I really mean is don't assume updates are backwards compatible...
Hmmm - they are meant to be. Sometimes an error is made but it's not THAT often. One thing that does occur is the following: a) things are going along just fine. b) A user posts a problem to the list. This turns out to be some some combination of DLLS, use of export, multiple instantications, virtual base classes, sharead pointer, collection serialization all nested with the user types. c) Something is wrong, but it's not easy to figure out. 1) Turns out to be a library bug. Does happen sorry. But the fix ends up breaking someone's usage. Hopefully, this just results in a compile time error which is easily fixed and we're done. 2) More often, it turns out to be an error on the part of the user about what the library can do or be expected to do. At this point I have two choices. i) resign my self to answering the same question forever. ii) ignore he user's problem, in which case he goes around reporting that "the serialization library is buggy" which of course annoys the hell out of me. iii) Enhance the code to trap the user error at compiler or maybe runtime. An explicit crash ASAP is better than a buried/hidden problem? Unfortunately, this will often trap errors in older code which are now report as new "bugs". What they really were were buried traps that no one has knowingly stepped in yet. This is not meant to be a rant. I'm just trying to make the library such that it's easy to use and hard to mis-use. I don't know how successful this effort has been, that is how many people have tried the library and found to frustrating to use, but there it is. Robert Ramey
Robert Ramey wrote:
John C wrote:
I think this was the main cause of my problem, and this alone might make it work in boost 1.40.0. Since the header file that uses this is in a shared object file that in some cases cannot have any boost dependencies, I had a forward declaration for base_object. I had to remove the forward declaration and #def in the inclusion of the boost export.hpp header for the BOOST_SERIALIZATION_BASE_OBJECT_NVP macro.
It's hard for me to guess what's going to happen if you start messing with the header - especiallly if you only reveal this after the fact.
In order to limit dependencies, I would suggest a different technique. Don't use inline definiition. Use the following in your class declaration:
template<class Archive> void serialization(Archive & ar, const unsigned int version);
In a *.cpp file define the template and explicitly instantiate it for the archive types that you use. This will permit you to confine the inclusion of serialization library headers to a smaller set of files.
When using serialization code (or any template code) with DLLS this technique will also address another problem which is starting to come up - Multiple (and potentially conflicting) template instantiations. This could lead to hellish debug scenarios as well as code bloat. In some cases the library can now detect this problem, but I had to suppress the trap because it broke too much user code. (That is, it detected too many problems in user code.) When I have nothing else to do, I plan to revisit this and provide a trap that the user will be able to explicitly override. It might not help, but at least the user won't be able to say he wasn't warned.
The moral of the story: If you are upgrading boost versions, don't assume the serialization library hasn't changed drastically, especially if you are serializing polymorphic types and even if it works fine in Windows.
Well, the changes didn't seem drastic to me. I think that is an overly harsh and missleading characterisation.
Thanks for the help Robert....
Your welcome.
Robert Ramey
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Well, I can say from extensive (and probably out of the ordinary) use of the serialization library that it is NOT buggy, so hopefully anything I have said did not imply it. In my opinion, templated code can be very complex and compiler messages related to it can sometimes be extremely hard to decipher, which is where I think most people run into issues. If you are open to any suggestions on ways that I think might help other users of the library, it doesn't look like the html here: http://www.boost.org/doc/libs/1_42_0/libs/serialization/doc/index.html has been updated in a while. For my case particularly, the portion in the tutorial on serializing Derived Classes does not mention the use of the BOOST_SERIALIZATION_BASE_OBJECT_NVP macro. I could see a first time user trying the given code, running into issues, and then possibly deciding the library is buggy since they couldn't figure out how to get it working. I found the macro in someone else's post, which I then googled to figure out what it was; then I found the boost/libs/serialization/test directory. Everything in this directory I think can answer probably any question someone might have about the serialization library usage, but they are most likely going to look to the above link for help. I also noticed that the release notes for boost 1.42.0 do not mention updates for the serialization library - maybe I just missed them? I at first didn't even bother looking at the latest release (and I don't think 1.41.0 mentioned anything either) until you said something... Robert Ramey wrote:
John C wrote:
Yeah, sorry, I suppose that sounds worse than what I intended. I guess what I really mean is don't assume updates are backwards compatible...
Hmmm - they are meant to be. Sometimes an error is made but it's not THAT often. One thing that does occur is the following:
a) things are going along just fine. b) A user posts a problem to the list. This turns out to be some some combination of DLLS, use of export, multiple instantications, virtual base classes, sharead pointer, collection serialization all nested with the user types. c) Something is wrong, but it's not easy to figure out. 1) Turns out to be a library bug. Does happen sorry. But the fix ends up breaking someone's usage. Hopefully, this just results in a compile time error which is easily fixed and we're done. 2) More often, it turns out to be an error on the part of the user about what the library can do or be expected to do. At this point I have two choices. i) resign my self to answering the same question forever. ii) ignore he user's problem, in which case he goes around reporting that "the serialization library is buggy" which of course annoys the hell out of me. iii) Enhance the code to trap the user error at compiler or maybe runtime. An explicit crash ASAP is better than a buried/hidden problem? Unfortunately, this will often trap errors in older code which are now report as new "bugs". What they really were were buried traps that no one has knowingly stepped in yet.
This is not meant to be a rant. I'm just trying to make the library such that it's easy to use and hard to mis-use. I don't know how successful this effort has been, that is how many people have tried the library and found to frustrating to use, but there it is.
Robert Ramey
Robert Ramey wrote:
John C wrote:
I think this was the main cause of my problem, and this alone might make it work in boost 1.40.0. Since the header file that uses this is in a shared object file that in some cases cannot have any boost dependencies, I had a forward declaration for base_object. I had to remove the forward declaration and #def in the inclusion of the boost export.hpp header for the BOOST_SERIALIZATION_BASE_OBJECT_NVP macro.
It's hard for me to guess what's going to happen if you start messing with the header - especiallly if you only reveal this after the fact.
In order to limit dependencies, I would suggest a different technique. Don't use inline definiition. Use the following in your class declaration:
template<class Archive> void serialization(Archive & ar, const unsigned int version);
In a *.cpp file define the template and explicitly instantiate it for the archive types that you use. This will permit you to confine the inclusion of serialization library headers to a smaller set of files.
When using serialization code (or any template code) with DLLS this technique will also address another problem which is starting to come up - Multiple (and potentially conflicting) template instantiations. This could lead to hellish debug scenarios as well as code bloat. In some cases the library can now detect this problem, but I had to suppress the trap because it broke too much user code. (That is, it detected too many problems in user code.) When I have nothing else to do, I plan to revisit this and provide a trap that the user will be able to explicitly override. It might not help, but at least the user won't be able to say he wasn't warned.
The moral of the story: If you are upgrading boost versions, don't assume the serialization library hasn't changed drastically, especially if you are serializing polymorphic types and even if it works fine in Windows.
Well, the changes didn't seem drastic to me. I think that is an overly harsh and missleading characterisation.
Thanks for the help Robert....
Your welcome.
Robert Ramey
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
-- View this message in context: http://old.nabble.com/undefined-reference-to-base_object-tp28417529p28439386... Sent from the Boost - Users mailing list archive at Nabble.com.
participants (2)
-
John C
-
Robert Ramey