Topic: Deletion of Derived Type through pointer to Base Type
Author: monkey@mninter.net ("Ken Durden")
Date: Tue, 29 Oct 2002 04:23:06 +0000 (UTC) Raw View
I'm having a friendly debate with someone where I work, is the following
code well-defined and guaranteed not to leak memory?
Specifically, the concern my friend has was that since Base does not have a
virtual destructor, the compiler is unable to know the correct amount of
memory to de-allocate. My thoughts were that having a virtual destructor
simply insures that a.) the correct destructor is called, and b.) the
correct operator delete is called if the default is overriden. We agreed
that on our platform, MSVC6, this code executes correctly, but his position
was that the standard does not guarantee this.
Anyone care to confirm or deny my notion that this is legal code.
Thanks,
-ken
struct Base
{
long n[10];
};
struct Derived : public Base
{
long x[12];
};
int main()
{
Base * pBase = new Derived;
delete pBase;
}
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: vAbazarov@dAnai.com ("Victor Bazarov")
Date: Tue, 29 Oct 2002 18:29:32 +0000 (UTC) Raw View
"Ken Durden" <monkey@mninter.net> wrote...
> I'm having a friendly debate with someone where I work, is the following
> code well-defined and guaranteed not to leak memory?
>
> Specifically, the concern my friend has was that since Base does not have
a
> virtual destructor, the compiler is unable to know the correct amount of
> memory to de-allocate. My thoughts were that having a virtual destructor
> simply insures that a.) the correct destructor is called, and b.) the
> correct operator delete is called if the default is overriden. We agreed
> that on our platform, MSVC6, this code executes correctly, but his
position
> was that the standard does not guarantee this.
>
> Anyone care to confirm or deny my notion that this is legal code.
Your motion is denied. The code is illegal. The base class has
to have a virtual destructor. See 5.3.5/3. If the destructor is
not virtual, the behaviour is undefined, which includes seemingly
"correct" behaviour exhibited by your compiler.
>
> Thanks,
> -ken
>
> struct Base
> {
> long n[10];
> };
>
> struct Derived : public Base
> {
> long x[12];
> };
>
> int main()
> {
> Base * pBase = new Derived;
> delete pBase;
> }
Victor
--
Please remove capital A's from my address when replying by mail
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: kanze@gabi-soft.de (James Kanze)
Date: Tue, 29 Oct 2002 18:29:54 +0000 (UTC) Raw View
monkey@mninter.net ("Ken Durden") wrote in message
news:<urs22uaq5nhrf2@corp.supernews.com>...
> I'm having a friendly debate with someone where I work, is the
> following code well-defined and guaranteed not to leak memory?
It contains undefined behavior. It may leak memory. It may also do
just about anything else. On a lot of systems, it could cause a crash
sometimes (much) later in the program, for example.
> Specifically, the concern my friend has was that since Base does not
> have a virtual destructor, the compiler is unable to know the correct
> amount of memory to de-allocate.
Because Base does not have a virtual destructor, the behavior is
undefined. Typically, except in special cases, the compiler will not
even know the correct address of the memory to de-allocate, much less
the size.
> My thoughts were that having a virtual destructor simply insures that
> a.) the correct destructor is called, and b.) the correct operator
> delete is called if the default is overriden.
The standard is quite clear: if the destructor is not virtual, and the
dynamic type is different than the static type of the expression, you
have undefined behavior.
> We agreed that on our platform, MSVC6, this code executes correctly,
> but his position was that the standard does not guarantee this.
Not only does the standard not guarantee it, but even with MSVC6, it
only works correctly in special cases.
> Anyone care to confirm or deny my notion that this is legal code.
Totally illegal.
> struct Base
> {
> long n[10];
> };
struct Base2 { char c[ 100 ] } ;
> struct Derived : public Base
struct Derived : Base2, Base
> {
> long x[12];
> };
> int main()
> {
> Base * pBase = new Derived;
> delete pBase;
> }
Try this example with multiple inheritance, as above, and see what
happens. I don't know of an implementation which will get it right,
although the exact symptoms will vary. In almost every case, the
implementation will pass the wrong address to the operator delete
function. What happens next depends on the implementation of the
operator delete function; you might get a memory leak, you might get an
immediate core dump, or you might just subtly corrupt the free space
arena, and introduce strange bugs in totally unrelated parts of the
program.
All of which is fine as far as the standard is concerned. Undefined
behavior is undefined behavior, and anything the implementation does is
fine as far as the standard is concerned.
--
James Kanze mailto:jkanze@caicheuvreux.com
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: ron@sensor.com ("Ron Natalie")
Date: Tue, 29 Oct 2002 20:32:33 +0000 (UTC) Raw View
""Ken Durden"" <monkey@mninter.net> wrote in message news:urs22uaq5nhrf2@corp.supernews.com...
> Specifically, the concern my friend has was that since Base does not have a
> virtual destructor, the compiler is unable to know the correct amount of
> memory to de-allocate
It's worse than that. The standard declares deleting a derived object through
a base class pointer without a virtual destructor as undefined behavior.
Unfortunately, in most instances all that gets hosed up is the wrong destructor
could get called. However, it's quite possible in many circumstances to hose
up the deallocation function in much worse ways than just having the wrong
size to worry about. STAY AWAY FROM UNDEFINED BEHAVIOR.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: Bart.van.Ingen.Schenau@ict.nl (Bart van Ingen Schenau)
Date: Wed, 30 Oct 2002 20:25:44 +0000 (UTC) Raw View
On Tue, 29 Oct 2002 04:23:06 +0000 (UTC), monkey@mninter.net ("Ken
Durden") wrote:
>I'm having a friendly debate with someone where I work, is the following
>code well-defined and guaranteed not to leak memory?
>
>Specifically, the concern my friend has was that since Base does not hav=
e a
>virtual destructor, the compiler is unable to know the correct amount of
>memory to de-allocate. My thoughts were that having a virtual destructor
>simply insures that a.) the correct destructor is called, and b.) the
>correct operator delete is called if the default is overriden. We agreed
>that on our platform, MSVC6, this code executes correctly, but his posit=
ion
>was that the standard does not guarantee this.
>
>Anyone care to confirm or deny my notion that this is legal code.
Unfortunately (for you), the code exhibits undefined behaviour:
[expr.delete] 5.3.5 Delete
3 In the first alternative (delete object), if the static type of the
operand is different from its dynamic type, the static type shall be a
base class of the operand=92s dynamic type and the static type shall
have a virtual destructor or the behavior is undefined. [...]
>
>Thanks,
>-ken
>
>struct Base
>{
>long n[10];
>};
>
>struct Derived : public Base
>{
>long x[12];
>};
>
>int main()
>{
>Base * pBase =3D new Derived;
>delete pBase;
>}
>
Bart v Ingen Schenau
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]
Author: cpdaniel@pacbell.net ("Carl Daniel")
Date: Wed, 30 Oct 2002 20:26:51 +0000 (UTC) Raw View
""Ken Durden"" <monkey@mninter.net> wrote in message
news:urs22uaq5nhrf2@corp.supernews.com...
> I'm having a friendly debate with someone where I work, is the following
> code well-defined and guaranteed not to leak memory?
>
> Specifically, the concern my friend has was that since Base does not have
a
> virtual destructor, the compiler is unable to know the correct amount of
> memory to de-allocate. My thoughts were that having a virtual destructor
> simply insures that a.) the correct destructor is called, and b.) the
> correct operator delete is called if the default is overriden. We agreed
> that on our platform, MSVC6, this code executes correctly, but his
position
> was that the standard does not guarantee this.
>
> Anyone care to confirm or deny my notion that this is legal code.
Undefined.
5.3.5/3 says:
In the first alternative (delete object), if the static type of the operand
is different from its dynamic type, the
static type shall be a base class of the operand s dynamic type and the
static type shall have a virtual
destructor or the behavior is undefined.
-cd
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]