Re: unloading plugins (i.e. shared objects) nearly impossible!
Earl Purple wrote:
davidbaraff@gmail.com wrote:
[...]
Well, guess what -- when I destroy that boost::any? My
program crashes. Why? Because my plugin, through the magic
of templating, actually built me a derived class that was
internal to boost::any, with a virtual destructor, and now
that I've unloaded the plugin, I can't call the
destructor!!!!
Correct, you can't. You should have got your plugin to clean
it up before you unplugged it.
You miss the point. He can't. The plugin cannot know about
them, because they aren't the object the plugin returned, they
are copies of it. He's using value semantics, which logically
should work exactly like int. And you certainly wouldn't say
that you cannot unload the plugin because there might be a copy
of an int it returned somewhere.
Said another way: template programming has made it extremely
simple and commonplace for plugin code to build all sorts of
virtual functions behind your back. You don't realize that
by passing around simple containers like boost::any, holding
simple types that are not at all defined by your plugin,
that you are still carting around with it some global
symbols that *DO* belong, uniquely, to your plugin.
They're not global, they belong to your plugin.
They're local variables, on the stack. How can a local variable
belong to my plugin?
My confidence that I can ever safely unload a plugin just plummetted.
By a plugin I assume you mean a library that you open with
dlopen() or LoadLibrary or whatever the equivalent is on your
platform, and you've then closed the library, thus meaning you
cannot use any of the symbols that it created. If you still
have symbols from the library around, do not close the
library. That includes any exceptions it may have thrown so if
you are going to catch these exceptions, be certain the
library is still open. I have made that error before.
Again, it depends. Exceptions propagate by copy, so presumably,
you should be safe:-). In fact, of course, you catch by
reference, and count on the polymorphism, so you probably know
you're not safe.
The problem is related to polymorphism. Polymorphism allows
calling the destructor (or other functions) without the code
being aware of what is actually being called at the call site.
Generally, polymorphic objects don't copy, and you know enough
not to keep the object created by the plugin, so you're safe.
Once polymorphism starts copying, you have to watch out,
however, and if the polymorphism is hidden (as in the case of
boost::any), the restriction really should be documented
(although I'll admit that before this thread, the necessity of
this documentation didn't occur to me, either).
In the meantime, I'd say that you should be very, very
suspicious of any object which behaves polymorphicly, in any
way, even if no C++ polymorphism is visible. Boost::any is a
good example, Coplien's letter/envelope idiom as well, and there
are doubtlessly others.
--
James Kanze GABI Software
Conseils en informatique orient?e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S?mard, 78210 St.-Cyr-l'?cole, France, +33 (0)1 30 23 00 34
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]