Re: [boost] [1.37.0][serialization] Assertion failed at libs/serialization/src/extended_type_info.cpp:92

Anything I can do about this? What does this assertion mean?
My setup: Linux 64Bit, gcc 4.2.4, serialization is used for polymorphic objects loaded from different shared libraries, shared libraries are loaded with dlopen(RTLD_GLOBAL|RTLD_LAZY).
Assertion (extended_type_info.cpp:92) occurs during program termination (after main returned), during dlclose().
If anything else isn't possible, would it be appropriate to change the related code (before the release!) from:
assert(start != end);
// remove entry in map which corresponds to this type do{ if(this == *start) x.erase(start++); else ++start; }while(start != end);
After looking at this code again I have the impression that it is broken anyways. You can't safely increment an iterator after deleting the object it points to: erase(start++). This code relies on the fact that in order to be incremented the iterator doesn't need the object it points to (which at least for lists is a wrong assumption). Regards Hartmut
To:
assert(start != end);
// remove entry in map which corresponds to this type while(start != end) { if(this == *start) x.erase(start++); else ++start; }
Which wouldn't remove the problem, but at least avoids hanging the program if assertions are off...
Regards Hartmut

Hartmut Kaiser escribió:
assert(start != end);
// remove entry in map which corresponds to this type do{ if(this == *start) x.erase(start++); else ++start; }while(start != end);
After looking at this code again I have the impression that it is broken anyways. You can't safely increment an iterator after deleting the object it points to: erase(start++).
I think your objection is wrong: erase(start++) is perfectly safe because the incrementing op is executed before erase is invoked. Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

Hartmut Kaiser escribió:
assert(start != end);
// remove entry in map which corresponds to this type do{ if(this == *start) x.erase(start++); else ++start; }while(start != end);
After looking at this code again I have the impression that it is broken anyways. You can't safely increment an iterator after deleting the object it points to: erase(start++).
I think your objection is wrong: erase(start++) is perfectly safe because the incrementing op is executed before erase is invoked.
Actually, to be concise, you're invoking undefined behavior. The Standard doesn't guarantee any execution order of operations in this context. The only thing which is guaranteed is, that the operation executed by erase() uses the initial value and afterwards start has been incremented (well, whatever happens if you increment an iterator after erasing the element it's pointing to). Regards Hartmut

Hartmut Kaiser:
Actually, to be concise, you're invoking undefined behavior. The Standard doesn't guarantee any execution order of operations in this context.
It does, there is a sequence point before the call.

Hartmut Kaiser:
Actually, to be concise, you're invoking undefined behavior. The Standard doesn't guarantee any execution order of operations in this context.
It does, there is a sequence point before the call.
Ok, there is always something new to learn out there. Thanks! Regards Hartmut PS: Anyway, that doesn't fix my assertion in the first place either :-P

Hartmut Kaiser escribió:
Hartmut Kaiser escribió:
assert(start != end);
// remove entry in map which corresponds to this type do{ if(this == *start) x.erase(start++); else ++start; }while(start != end);
After looking at this code again I have the impression that it is
broken
anyways. You can't safely increment an iterator after deleting the
object it
points to: erase(start++).
I think your objection is wrong: erase(start++) is perfectly safe because the incrementing op is executed before erase is invoked.
Actually, to be concise, you're invoking undefined behavior. The Standard doesn't guarantee any execution order of operations in this context. The only thing which is guaranteed is, that the operation executed by erase() uses the initial value and afterwards start has been incremented (well, whatever happens if you increment an iterator after erasing the element it's pointing to).
I still disagree; start++ produces a side effect (std 1.9.7, emphasis mine): "Accessing an object designated by a volatile lvalue (3.10), *modifying an object* [...] are all side effects, which are changes in the state of the execution environment.[...] At certain specified points in the execution sequence called sequence points, all side effects of previous evaluations shall be complete and no side effects of subsequent evaluations shall have taken place." and as such, it must have taken place by the time the function erase is invoked (std 1.9.17): "When calling a function (whether or not the function is inline), there is a sequence point after the evaluation of all function arguments (if any) which takes place before execution of any expressions or statements in the function body .[...]" Am i missing something? Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

Actually, to be concise, you're invoking undefined behavior. The Standard doesn't guarantee any execution order of operations in this context. The only thing which is guaranteed is, that the operation executed by erase() uses the initial value and afterwards start has been incremented (well, whatever happens if you increment an iterator after erasing the element it's pointing to).
I still disagree; start++ produces a side effect (std 1.9.7, emphasis mine):
"Accessing an object designated by a volatile lvalue (3.10), *modifying an object* [...] are all side effects, which are changes in the state of the execution environment.[...] At certain specified points in the execution sequence called sequence points, all side effects of previous evaluations shall be complete and no side effects of subsequent evaluations shall have taken place."
and as such, it must have taken place by the time the function erase is invoked (std 1.9.17):
"When calling a function (whether or not the function is inline), there is a sequence point after the evaluation of all function arguments (if any) which takes place before execution of any expressions or statements in the function body .[...]"
Ok, I'm wrong. But I remember at least one problem in the past I have had exactly because of this. But that just might have been a non-conforming compiler playing games on me. Thanks for the explanations. Regards Hartmut

Hartmut Kaiser wrote:
Anything I can do about this? What does this assertion mean?
My setup: Linux 64Bit, gcc 4.2.4, serialization is used for polymorphic objects loaded from different shared libraries, shared libraries are loaded with dlopen(RTLD_GLOBAL|RTLD_LAZY).
Assertion (extended_type_info.cpp:92) occurs during program termination (after main returned), during dlclose().
If anything else isn't possible, would it be appropriate to change the related code (before the release!) from:
assert(start != end);
// remove entry in map which corresponds to this type do{ if(this == *start) x.erase(start++); else ++start; }while(start != end);
After looking at this code again I have the impression that it is broken anyways.
Yes, but IMHO not for the reason you mention. Certainly I wouldn't let the start++/++start "dance" pass a code review. PS: don't use tab characters in posts! :-) -- Genny

Anything I can do about this? What does this assertion mean?
My setup: Linux 64Bit, gcc 4.2.4, serialization is used for
objects loaded from different shared libraries, shared libraries are loaded with dlopen(RTLD_GLOBAL|RTLD_LAZY).
Assertion (extended_type_info.cpp:92) occurs during program termination (after main returned), during dlclose().
If anything else isn't possible, would it be appropriate to change
Hartmut Kaiser wrote: polymorphic the
related code (before the release!) from:
assert(start != end);
// remove entry in map which corresponds to this type do{ if(this == *start) x.erase(start++); else ++start; }while(start != end);
After looking at this code again I have the impression that it is broken anyways.
Yes, but IMHO not for the reason you mention. Certainly I wouldn't let the start++/++start "dance" pass a code review.
Agreed.
PS: don't use tab characters in posts! :-)
It's a raw copy of the code, so there have to be tabs in the source files... Regards Hartmut
participants (4)
-
Gennaro Prota
-
Hartmut Kaiser
-
joaquin@tid.es
-
Peter Dimov