[Serialization] assert in void_caster
Hello, I have the static library with two classes, "base" and "derived". class base { public: base():a(0){}; virtual ~base(){}; private: friend class boost::serialization::access; template<class Archive> void serialize(Archive & ar, const unsigned int version) { ar & a; } private: int a; }; class derived: public base { public: derived():b(0){}; virtual ~derived(){}; private: friend class boost::serialization::access; template<class Archive> void serialize(Archive & ar, const unsigned int version) { ar & boost::serialization::base_object<base>(*this); ar & b; } private: int b; }; This static library is linked to two dynamic libraries. For example, dll_a.dll and dll_b.dll. When I try to load those dlls in my application (via LoadLibrary), I get assert in void_cast.cpp (225): std::pair<void_cast_detail::set_type::const_iterator, bool> result; result = s.insert(this); assert(result.second); Is it by design? Or I missed something? I am using boost v1.43 and VS 10 on Windows 7. Thank you in advance. Alex
This static library is linked to two dynamic libraries. For example, dll_a.dll and dll_b.dll. When I try to load those dlls in my application (via LoadLibrary), I get assert in void_cast.cpp (225):
std::pair<void_cast_detail::set_type::const_iterator, bool> result; result = s.insert(this); assert(result.second);
Is it by design? Or I missed something?
I am using boost v1.43 and VS 10 on Windows 7.
I believe this is addressed in 1.44 Robert Ramey
Thank you in advance.
Alex
This static library is linked to two dynamic libraries. For example, dll_a.dll and dll_b.dll. When I try to load those dlls in my application (via LoadLibrary), I get assert in void_cast.cpp (225):
std::pair<void_cast_detail::set_type::const_iterator, bool> result; result = s.insert(this); assert(result.second);
Is it by design? Or I missed something?
I am using boost v1.43 and VS 10 on Windows 7.
I believe this is addressed in 1.44
Robert Ramey
Thank you in advance.
Alex
Thank you for quick response! I will wait for 1.44. Best regards, Alex
This static library is linked to two dynamic libraries. For example, dll_a.dll and dll_b.dll. When I try to load those dlls in my application (via LoadLibrary), I get assert in void_cast.cpp (225):
std::pair<void_cast_detail::set_type::const_iterator, bool> result; result = s.insert(this); assert(result.second);
Is it by design? Or I missed something?
I am using boost v1.43 and VS 10 on Windows 7.
I believe this is addressed in 1.44
Robert Ramey
Thank you in advance.
Alex
Hello Robert, I tried to build boost serialize from trunk, but it seems the problem still exist. Is it suppose to be fixed in trunk? Or should I wait for 1.44 beta or stable release? Thank you, Alex
Alex Parkhomenko wrote:
I believe this is addressed in 1.44
Robert Ramey
Thank you in advance.
Alex
Hello Robert,
I tried to build boost serialize from trunk, but it seems the problem still exist. Is it suppose to be fixed in trunk? Or should I wait for 1.44 beta or stable release?
Hmmm - then I must be wrong. maybe the best would be to open a track ticket for it. Robert Ramey
This static library is linked to two dynamic libraries. For example, dll_a.dll and dll_b.dll. When I try to load those dlls in my application (via LoadLibrary), I get assert in void_cast.cpp (225):
std::pair<void_cast_detail::set_type::const_iterator, bool> result; result = s.insert(this); assert(result.second);
Is it by design? Or I missed something?
I am using boost v1.43 and VS 10 on Windows 7.
Thank you in advance.
Alex
The same assert fired here too but for a slightly different reason. For some classes the base derived relationship is registered by calling void_cast_register directly and at the same time by calling the serialize member function of the base class from the serialize member function of the derived class. This never caused any problems for us in boost 1.34.1. As far as I understand the assert fires because the base derived relationship is registered multiple times. But is this really a problem? We placed the void_cast_register call in a macro that exists in the implementation of every class anyway to be sure the base derived relationship was registered. Now we have to solve this differently because otherwise classes that have a serialize function (most don't) will trigger the assert at startup. Is it save to uncomment the assert? Are there real world scenarios when this assert is helpful? Thanks
As far as I understand the assert fires because the base derived relationship is registered multiple times. But is this really a problem? We placed the void_cast_register call in a macro that exists in the implementation of every class anyway to be sure the base derived relationship was registered. Now we have to solve this differently because otherwise classes that have a serialize function (most don't) will trigger the assert at startup. Is it save to uncomment the assert? Are there real world scenarios when this assert is helpful?
This assert fires when code with the same signature is found in multiple code modules. Could it be a problem? It could. Is this a problem? I can't say - it would depend.... It's been my philosophy in implementing the library to trap everything that could be a problem. That is, the intention is that the library never silently fail. The cost of finding the source of even one silent failure dwarfs the relatively cost of being forced to explicitly consider a potential problem. In this scenario - code with the same signature exists in different DLLS. But there's no way to guarentee that it is in fact the same code!!!. If one mixed different versions of the DLLs, one could easiliy have an error which is likely impossible to find. Then I get an report on the list which has in the title "serialization library doesn't work". Then I'm stuck in the position of proving that the library works. But to do this I have to help a user track through his code. And of course this is likely a huge project as it's spread accross several DLLS which call each other. You can imagine how much I enjoy that. So I trap the problem. There a couple of places where I do this. I thought I commented it out because a user had a problem. Now I don't remember whether I did this, or whether I just told him to comment it out. If this were to happen to me, I would conclude that my code is not organized optimally. I would re-organize the code so that the asserts can never be called. This would guarentee that the one definition rule is respected and that DLLS will always be consistent. This in turn will mean that I have truely plugable modules. It would also mean that my package of shipping executables will be as small as possible - not code bloat. However, this is not always practical. If serializaition is added to a project which is already done - the code re-organization required to implement the above may just be two much effort. In any event, my future strategy will be: a) leave in the asserts b) provide some sort of setting "no-odr-enforcement" to suppress the enforcement of this rule. The hope is that when one steps into undefined territory, you'll get the assert. He'll complain and then have to explicitly override it and I'll be off the hook. I haven't done this yet as I've been busy - but that's my plan. Robert Ramey
On Tue, Jun 29, 2010 at 10:13 AM, Robert Ramey <ramey@rrsd.com> wrote:
As far as I understand the assert fires because the base derived relationship is registered multiple times. But is this really a problem? We placed the void_cast_register call in a macro that exists in the implementation of every class anyway to be sure the base derived relationship was registered. Now we have to solve this differently because otherwise classes that have a serialize function (most don't) will trigger the assert at startup. Is it save to uncomment the assert? Are there real world scenarios when this assert is helpful?
In this scenario - code with the same signature exists in different DLLS. But there's no way to guarentee that it is in fact the same code!!!. If one mixed different versions of the DLLs, one could easiliy have an error which is likely impossible to find.
On Windows, the standard library goes to great lengths to make std::type_info objects that identify the same type from different DLLs compare equal. This could lead to problems in case the DLLs have different version of the type, but it doesn't mean that the use is invalid when all DLLs have identical copies of the type. I think the same logic applies to void_cast_register: when multiple registrations for the same type from different DLLs occur, it should assume that the types are identical. Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode
Emil Dotchevski wrote:
On Windows, the standard library goes to great lengths to make std::type_info objects that identify the same type from different DLLs compare equal. This could lead to problems in case the DLLs have different version of the type, but it doesn't mean that the use is invalid when all DLLs have identical copies of the type.
Of course not. BUT there is no way to tell. Now one has introduced a wild card variable into his program. Its worse, a test program might fail on one machine and pass on another just because a different DLL is loaded. Or, a problem might suddenly appear when something totally related is installed. DLL hell of the worst kind.
I think the same logic applies to void_cast_register: when multiple registrations for the same type from different DLLs occur, it should assume that the types are identical.
lol - That would be fine by me if when the application inexplicably crashes or fails in some way, users wouldn't assume that the source of the problem is in the serialization library. In my view, including the same code in different DLLS is a symptom of poor code organization. So my view is to trap it (at least in debug builds) and permit the user to override the trap if he is willing to be responsable for the consequences. Robert Ramey
On Tue, Jun 29, 2010 at 12:52 PM, Robert Ramey <ramey@rrsd.com> wrote:
Emil Dotchevski wrote:
On Windows, the standard library goes to great lengths to make std::type_info objects that identify the same type from different DLLs compare equal. This could lead to problems in case the DLLs have different version of the type, but it doesn't mean that the use is invalid when all DLLs have identical copies of the type. <snip> In my view, including the same code in different DLLS is a symptom of poor code organization.
Nevertheless, it is valid code organization and the standard library's type_info implementation and exception handling implementation has specific support for it. I think that Boost libraries should support it as well.
So my view is to trap it (at least in debug builds) and permit the user to override the trap if he is willing to be responsable for the consequences.
Oh, I am sorry I didn't understand that there is a way for the assert to be avoided -- nevermind then! Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode
Emil Dotchevski wrote:
On Tue, Jun 29, 2010 at 12:52 PM, Robert Ramey <ramey@rrsd.com> wrote:
So my view is to trap it (at least in debug builds) and permit the user to override the trap if he is willing to be responsable for the consequences.
Oh, I am sorry I didn't understand that there is a way for the assert to be avoided -- nevermind then!
There isn't now. It's my intention to implement this to reconcile these differing points of view. Robert Ramey
participants (4)
-
Alex Parkhomenko
-
Emil Dotchevski
-
Markus Henschel
-
Robert Ramey