
"Robert Ramey" <ramey@rrsd.com> writes:
David Abrahams wrote:
"Robert Ramey" <ramey@rrsd.com> writes:
David Abrahams wrote:
"Emil Dotchevski" <emildotchevski@hotmail.com> writes:
Or did I completely misunderstand the documentation? Robert, was the intended meaning that *if* you explicitly call a function from foo.cpp, then using the class export macro guarantees that class foo is properly registered with the serialization library?
My intention is and was that proper registration will occur whether or not the type is explicitly referred to.
"Whether the type is explicitly referred to" is completely irrelevant. The question is whether any objects or functions from the translation unit containing the EXPORT are used.
Did you intend that proper registration occur even if no objects or functions from the translation unit containing the EXPORT are used?
You didn't answer my question. Will you answer the question?
I don't see how one can determine at compile time whether or not an object of a particular type is going to be used. In fact, it may well vary from one exectution run to the next. The situation I had in mind is that of serialization of derived through an abstract base class.
"Of a particular type" is irrelevant. The question is whether any objects or functions in the TU are going to be used. The compiler only has to prove that none will be used, and it can optimize out the TU. No, obviously that doesn't happen at compile-time; it happens at link time.
suppose one is going to load an archive. The sequence of events is very roughly:
a) read the export tag b) look it up in the extended type info table c) using this pointer, lookup the deserializer function d) and invoke them
So the extended type info table has to be initialized with all the types that might be in the archive. This is what export attempts to do. But when compiled for release mode, some compilers drop the deseralization code. The results in a run time error "unregistered type". I always interpreted this as the compilers droping code that was never explicitly called. This is what occurs when we have an executable or dll which contains entry points never called. Some compilers provide the keyword "__export" to tell the compilers that such functions shouldn't be dropped even though they don't seem to be called. So I used these to be sure the the specified code didn't get dropped. Perhaps I should have described this but
but?
That was my goal and I believe it has been achieved for all compilers that boost supports.
I would be very surprised if that were the case for Metrowerks; as pointed out by Emil, that compiler is very good at optimizing out unused translation units.
Well, that would explain one reason we've had so much problem with this comipiler - its too conforming!!!
Maybe, but there's also one bug (at least).
Now it seems the question being raised is whether this is/was the right thing to do.
No, I don't think that is the question at all, at least, not mine. My question is what promises you can legitimately make to users about what will happen, and whether you have made your promises sufficiently explicit.
That's a legitimate thing to do, but I think you need to be very explicit about what you're doing.
Well, that's easy to fix. I guess that all we need to say is:
a) functionality of export cannot be guarenteed to be made to work on all compilers.
I don't think that's sufficiently precise. EXPORT works just fine as long as you ensure that some function in the TU gets called. You could have 50 EXPORTs and one dummy function in the TU, called from main(), that prevents it from getting linked out.
b) If you want your code to be guarenteed to be portable to other compilers, don't use export - use explicit registration instead.
Too big a hammer, IMO.
Do any of your tests actually exercise the case where the EXPORT is in a TU with no used functions or objects?
Well, I thought demo_pimpl did this - but I looked at it and it doesn't use export.
So I checked test_exported. Its only one translation unit so it doesn't explicitly test this situation - the derived class constructor is called explicitly. this could easily be moved to another *.cpp file to test this.
I did find one thing that was new to me and very interesting:
BOOST_CLASS_EXPORT(polymorphic_derived1)
// MWerks users can do this to make their code work
BOOST_SERIALIZATION_MWERKS_BASE_AND_DERIVED(polymorphic_base, polymorphic_derived1)
which I had never seen before. I don't know if this is related in some way.
Sure you have; I pointed it out to you very explicitly when I checked in the new export code. It's not related to the optimization; it is a workaround for the Metrowerks bug we've been discussing elsewhere in this thread.
- its just not guarenteed to be portable to new compilers.
Or new versions of existing compilers.
Obviously
Of course, if the compiler's docs say it will respect __export, then you're pretty darned safe in the future. -- Dave Abrahams Boost Consulting www.boost-consulting.com