Re: Virtual Destructor - Implication & Specification
On Apr 3, 5:50 pm, "John Moeller" <fishc...@gmail.com> wrote:
What if you compile and link dll.cpp in MinGW and compile and link
exe.cpp in MSVC++? Then you'll have called the glibc version (most
likely) of operator new, and the MSVCRT version (most likely) of
operator delete. Matching destructors will be called because they're
virtual, but that's not the point here. You're mismatching operators
new and delete. That's not a good thing.
Not true. First I would like to say I am glad you responded, because
this is precisely the line of reason that I have been trying so hard
to refute and make clear, at least in context of Windows.
Let us re-examine what happens when a delete expression within an EXE
is applied to a pointer to an object that was manufactured inside a
DLL:
1. The EXE loads the DLL into its process address space.
2. An object gets "manufactured" in DLL.
3. A DLL function returns pointer to this object to a function in the
EXE.
4. EXE invokes operator delete against the pointer.
5. The class declaration for object indicates that class has virtual
desctructor.
6. EXE delete operation involves finding 'scalar deleting destructor'
via v-table, invokes it.
7. 'scalar deleting destructor' *IS A WHOLY-FORMED FUNCTION INSIDE
THE DLL*.
8. 'scalar deleting destructor' invokes tilde (~) function against
space.
9. 'scalar deleting destructor' calls equivalent of C free() function
against space.
I highly suspect that it would not matter if the EXE is built with
MSVC and the DLL is built with MingW. The EXE code would still kick-
off the sequence in the same way, by simply locating the 'scalar
deleting destructor' via the v-table, and telling it to "do whatever
it is you need to do."
This is the essence of my thesis. There is a two-step process here:
1. invoking the tilde (~) function
2. calling free() against the allocated space
This two-step process is encapsulated in a function whose address is
stored in the v-table, and which the delete expression invokes.
If you're still not convinced, think about it this way:
If it so happens that a DLL is able to return a pointer to an object
to an EXE, then certainly, before yielding the pointer, the object is
fully-manufactured inside the DLL. But if the object is fully-
manufactured inside the DLL, then that means that the v-table for the
object is also fully manufactured, and a pointer to that v-table is
within the object . If the v-table is appropriately defined, then
that means that the code for invoking the (~) function and the free()
function are *** entirely within the DLL long before the DLL ever gets
the pointer. ***
Some of you might be reading this and thinking, "Well, technically,
there is nothing to stop the EXE from using its own tilde(~) function
and free() sequence...". This point of view would be incorrect. The
reason is that, by virtue of the virtual destructor, it is
indeterminate what object the pointer actually points to. In
practice, the EXE *must* find the right (~) function for the object at
run-time via the v-table (or virtual destructor if you prefer). It
also has to get the right size of the object by virtue of the virtual
destructor. These two requirements, coupled with the fact that the
implementation permits the use of DLL's, combine to allow one to, at
the very minimum, infer that this mechanism at play, without reverse-
assembling any code.
The only way that you can guarantee that they match up is to make sure
that you use the same build environment for both. That's not much of
a guarantee. People use DLL versions of open-source libraries all the
time in Windows. If the library designer isn't cautious enough to
either stick to a C-only interface, overload the new and delete
operators, or use a smart pointer that handles deallocation in the
same binary code as the allocation, then it's broken.
Just make the destructor virtual.
The only way to get around that is to override operator new and
operator delete in your classes, to guarantee that you call a
deallocation routine that matches your allocation routine. The
destructor isn't the same as the deallocator, and both have to be
considered. You're only considering one in your code.
This is actually incorrect in my opinion. As I stated earlier, I
think that Stroustrup made a very tiny mistake when he mixed the
exposition of utility of virtual destrutors with the utility of class-
specific new/delete. THESE TWO CONCEPTS ARE TOTALLY UNRELATED. If
you read closely the pages 421-222 when he talks about it, you will
see that the virtual destructor technique is used *solve* a problem
that would manifest in context of class-specific new/delete, _not_ the
other way around.
In other words, the virtual destructor technique is a technique that
has far broader implications that class-specific new/delete, and is
useful in its own right.
-Le Chaud Lapin-
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]