Boost logo

Boost :

From: Jim.Hyslop (jim.hyslop_at_[hidden])
Date: 2001-10-03 10:28:39


From: "David Abrahams" <david.abrahams_at_[hidden]>
> Could I expect to successfully dynamic_cast a B* to a C* or D*
> in code compiled into any arbitrary one of these libraries, even
> if libC and libD were not explicitly linked to libB?
Not in Windows.

To put this quite simplistically, from the compiler/linker's point of view,
the only difference between an EXE and a DLL (or any other executable image,
such as an OCX, SCR [screen saver] and so on) is the extension it gives the
final binary image (there are, of course, other details but those are not
relevant to the current discussion). This means that when your Windows
linker creates its DLL, it must resolve all symbol references. Therefore,
when you are building the DLL containing class C, the linker must be able to
find all B's member functions. This means that B must be exported from its
DLL, and both C and D must link to the export library.

You _can_ get away without linking libB, if you meet all the following
conditions:

- All of B's member functions are inline, in the header, or in a regular
(statically linked) library
- B does not have any static data members
- B's member functions do not refer to static non-member data (i.e. global
variables), unless that data is exported from another DLL.

If B has static data members, then one of two things will happen. Either
you'll get an unresolved external, or each DLL will contain its own copy of
the static data member.

In that situation, though, B's export library would be empty!

For example:

// file: b.h
class B
{
   int i;
public:
   virtual ~B() {}
   virtual void doSomething() {}
   virtual void aPureFn() = 0;
};

In this situation, each executable image that #includes b.h will generate
its own versions of the inline functions, and a vtable which points to those
functions (and has the RTTI information as well).

There is a danger to this. If you have this sequence of events:

DLL X creates a B object, or an object derived from B
DLL X gets unloaded
B object gets destroyed

(the sequence is actually a little more subtle than this, but that's the
broad strokes of it).

The pointers in B's vtable will all point to functions that were mapped into
the memory previously occupied by DLL X. But since X has been unloaded from
memory, those pointers now point at unmapped memory.

-- 
Jim

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk