Virtual dtor and placement new.

?

=?ISO-8859-15?Q?Tobias_G=FCntner?=

class B: public A {
..
};

A* obj = new(mem) B;
B* obj1 = new(mem) B;

...
CallDestructor( obj ); // resolves in template A, calling p->~A;
CallDestructor( obj1 ); // resolves in class B

That's not what I had in mind.

A* pA = new(mem) B;
DestructPtr Cleanup_mem = CallDestructor<B>;

// later
Cleanup_mem(mem); // Calls ((B*)mem)->~B();

It would be necessary to store both mem and Cleanup_mem somewhere to
perform the required destructor call. A smart-pointer could be modified
so that it calls Cleanup_pA(mem); instead of delete obj;
Uhm; first of all, you may not want all the objects in your application to
be virtual. For really high-speed aps, as the vtable and the objects are
unlikely to be kept near in memory, the memory cache flushes to access the
vtable and then the object repeatedly may cause an unacceptable operational
downgrade.

So why do you need deletion through a base class then? If you want to
call the derived class' destructor, you need a virtual function call (or
something similar, e.g. pointer to function) anyway.
If you don't want that extra level of indirection, you need to know the
exact type of the object you want to delete - no need to delete through
pointer to base in this case.
Secondly, it does not cure the problem, as the problem is
EXACTLY that of being unable to virtualize the destructor due to a lack in
C++ grammar definition:

As the others have already pointed out, according to the Standard it
should not be necessary, because a call to ~A() automatically results in
~B() (I didn't know that either when I wrote my first post)
 
G

Giancarlo Niccolai

template <class C>
void func( C *p ) {
p->~C();
}

int main ( void ) {

Base* bp = new Derived();
func( bp );

}


Output [ compiled with g++ (GCC) 3.4.0 ] :

destructing Derived
destructing Base



Best

Kai-Uwe Bux

[gian@head: tests]$ gcc -v
Reading specs from /usr/lib/gcc-lib/i486-slackware-linux/3.2.3/specs
Configured with: ../gcc-3.2.3/configure --prefix=/usr --enable-shared
--enable-threads=posix --enable-__cxa_atexit --disable-checking
--with-gnu-ld --verbose --target=i486-slackware-linux
--host=i486-slackware-linux
Thread model: posix
gcc version 3.2.3


Original code failing is:

template <class _Tp >
inline void destroy( _Tp *p )
{
if ( p != 0 ) {
p->~_Tp();
memFree( p );
}
}

this was failing specifically when trying to destroy a class derived from
std::list (the virtual constructor of the DERIVED hyerarcy not being
properly called). I did not dug to discover if the error was in std::
implementation or in the core compiler; I have now repeated the test you
posted, and it works, so it seem it was in stl implementation.

Bests and thanks

Giancarlo
 
G

Giancarlo Niccolai

Tobias said:
So why do you need deletion through a base class then? If you want to
call the derived class' destructor, you need a virtual function call (or
something similar, e.g. pointer to function) anyway.
If you don't want that extra level of indirection, you need to know the
exact type of the object you want to delete - no need to delete through
pointer to base in this case.

The point was being able to use a memory manager through a whole application
without making all the classes virtual, but only those that really needs
it.
As the others have already pointed out, according to the Standard it
should not be necessary, because a call to ~A() automatically results in
~B() (I didn't know that either when I wrote my first post)

Yes now I got it: I just stumbled on some mis-implementation of the standard
(probably, but not sure as now I eliminated the problem, and I am not going
to recreate it, in a implementation of std::list in older GCC ;-) that
drove me mad.

Thanks,
Giancarlo.
 
K

Kai-Uwe Bux

Giancarlo said:
Original code failing is:

template <class _Tp >
inline void destroy( _Tp *p )
{
if ( p != 0 ) {
p->~_Tp();
memFree( p );
}
}

Hm,


I am using a homegrown


template < typename T, typename Allocator > class pointer_to;

instead of raw pointers in my programms. Its deallocation method is
more or less exactly like your code above. It never failed me.


Now, you say:
this was failing specifically when trying to destroy a class derived from
std::list (the virtual constructor of the DERIVED hyerarcy not being
properly called).

Note that std::list<> does not have a virtual destructor. Thus,

std::list< SomeClass > *

cannot be used polymorphically. This is the reason that

(a) many fellows on this list strongly advise against deriving from
standard container classes, and

(b) I actually use two templates: pointer_to<T> and polymorphic_ptr<T>. The
first of which does not allow for polymorphism and the second of which
yields compile time errors if the base type T does not have virtual
functions.



Best

Kai-Uwe Bux
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,015
Latest member
AmbrosePal

Latest Threads

Top