473,327 Members | 2,094 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,327 software developers and data experts.

virtual function phenomenon

I found the following phenomenon in VC++ 2005:

struct A {};

struct B : public A
{
virtual ~B() {}
};

A* p = new B;
delete p; // crashes when executing this line

Does anyone have any insight into why it is crashing there?
Jul 22 '05 #1
4 1477

"Eric" <sh*****@yahoo.com> wrote in message
news:41********@news.bezeqint.net...
I found the following phenomenon in VC++ 2005:

struct A {};

struct B : public A
{
virtual ~B() {}
};

A* p = new B;
delete p; // crashes when executing this line

Does anyone have any insight into why it is crashing there?


Because C++ says that this is undefined behaviour. If you delete a derived
class though a base class pointer then the base class *must* have a virtual
destructor.

Change to this and you will be OK.

struct A
{
virtual ~A() {}
};

struct B : public A
{
};

john
Jul 22 '05 #2

"John Harrison" <jo*************@hotmail.com> wrote in message
news:30*************@uni-berlin.de...

"Eric" <sh*****@yahoo.com> wrote in message
news:41********@news.bezeqint.net...
I found the following phenomenon in VC++ 2005:

struct A {};

struct B : public A
{
virtual ~B() {}
};

A* p = new B;
delete p; // crashes when executing this line

Does anyone have any insight into why it is crashing there?

Because C++ says that this is undefined behaviour. If you delete a derived
class though a base class pointer then the base class *must* have a

virtual destructor.


I had thought that what would happen is that the derived class destructor
would not be called but I see you're right about the standard saying the
behavior is undefined. If I make B::~B non-virtual then it runs ok and B::~B
is not called.. However making B::~B virtual causes it to crash.
Is there any simple explanation of this particular implementation mechanism
that causes it to crash when B::~B is made virtual?
Jul 22 '05 #3

"Eric" <sh*****@yahoo.com> wrote in message
news:41********@news.bezeqint.net...

"John Harrison" <jo*************@hotmail.com> wrote in message
news:30*************@uni-berlin.de...

"Eric" <sh*****@yahoo.com> wrote in message
news:41********@news.bezeqint.net...
>I found the following phenomenon in VC++ 2005:
>
> struct A {};
>
> struct B : public A
> {
> virtual ~B() {}
> };
>
> A* p = new B;
> delete p; // crashes when executing this line
>
> Does anyone have any insight into why it is crashing there?
>


Because C++ says that this is undefined behaviour. If you delete a
derived
class though a base class pointer then the base class *must* have a

virtual
destructor.


I had thought that what would happen is that the derived class destructor
would not be called but I see you're right about the standard saying the
behavior is undefined. If I make B::~B non-virtual then it runs ok and
B::~B
is not called.. However making B::~B virtual causes it to crash.
Is there any simple explanation of this particular implementation
mechanism
that causes it to crash when B::~B is made virtual?


B contains a vtable, A does not. Therefore the A object embedded in the B
object is offset four bytes from the start of the whole object. Therefore
when you say delete p you are passing a pointer to the deallocation routine
that is different from the pointer that was allocated. At least that seems
to be what is happening on my platform. I bet if you add any virtual
function to A (not a destructor) it will no longer crash. Would still
technically be undefined behaviour of course.

Try this code, with and without the dummy function.

#include <iostream>
using namespace std;

class A
{
//virtual void dummy() {}
};

class B : public A
{
public:
virtual ~B() {}
};

int main()
{
B* b = new B();
A* a = b;
cout << "a = " << a << '\n';
cout << "b = " << b << '\n';
delete a;
}

john
Jul 22 '05 #4

"John Harrison" <jo*************@hotmail.com> wrote in message
news:30*************@uni-berlin.de...

"Eric" <sh*****@yahoo.com> wrote in message
news:41********@news.bezeqint.net...

"John Harrison" <jo*************@hotmail.com> wrote in message
news:30*************@uni-berlin.de...

"Eric" <sh*****@yahoo.com> wrote in message
news:41********@news.bezeqint.net...
>I found the following phenomenon in VC++ 2005:
>
> struct A {};
>
> struct B : public A
> {
> virtual ~B() {}
> };
>
> A* p = new B;
> delete p; // crashes when executing this line
>
> Does anyone have any insight into why it is crashing there?
>

Because C++ says that this is undefined behaviour. If you delete a
derived
class though a base class pointer then the base class *must* have a virtual
destructor.


I had thought that what would happen is that the derived class destructor would not be called but I see you're right about the standard saying the
behavior is undefined. If I make B::~B non-virtual then it runs ok and
B::~B
is not called.. However making B::~B virtual causes it to crash.
Is there any simple explanation of this particular implementation
mechanism
that causes it to crash when B::~B is made virtual?


B contains a vtable, A does not. Therefore the A object embedded in the B
object is offset four bytes from the start of the whole object. Therefore
when you say delete p you are passing a pointer to the deallocation

routine that is different from the pointer that was allocated. At least that seems
to be what is happening on my platform. I bet if you add any virtual
function to A (not a destructor) it will no longer crash. Would still
technically be undefined behaviour of course.


You're correct. I checked and the object layout is as follows:
VPTR < B*
A < A*
B

Adding a virtual function to A causes A to include the VPTR and then both A*
and B* point to the beginning of the object (the VPTR). This would seem to
be a logical implementation.

However, I tried it on the Borland compiler and there was no crashing and
the behavior was as I originally expected it would be.

It seems the Borland object layout with virtual B::~B is:
A < B* and A*
VPTR
B

and the Borland layout with virtual A::~A is:
VPTR < B* and A*
A
B
Jul 22 '05 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Roy Yao | last post by:
Hello, I need to pass a pointer to a callback function to the lower level modules. But the function is thought to be a virtual member one. How can I get the real address of the virtual...
23
by: heted7 | last post by:
Hi, Most of the books on C++ say something like this: "A virtual destructor should be defined if the class contains at least one virtual member function." My question is: why is it only for...
11
by: santosh | last post by:
Hello, I was going through the Marshal Cline's C++ FAQ-Lite. I have a doubt regarding section 33.10. Here he is declaring a pure virtual destructor in the base class. And again defining...
8
by: Floogle | last post by:
how do i create a virtual == operator. I've tried the following but it's incorrect... class Interface { ... public: virtual bool operator==(const Interface& rhs)const=0;
6
by: pakis | last post by:
I am having a problem of pure virtual function call in my project. Can anyone explaine me the causes of pure virtual function calls other than calling a virtual function in base class? Thanks
11
by: ypjofficial | last post by:
Hello All, So far I have been reading that in case of a polymorphic class ( having at least one virtual function in it), the virtual function call get resolved at run time and during that the...
10
by: John Goche | last post by:
Hello, page 202 of Symbian OS Explained by Jo Stichbury states "All virtual functions, public, protected or private, should be exported" then page 203 states "In the rare cases where a...
7
by: desktop | last post by:
This page: http://www.eptacom.net/pubblicazioni/pub_eng/mdisp.html start with the line: "Virtual functions allow polymorphism on a single argument". What does that exactly mean? I guess it...
17
by: Jess | last post by:
Hello, If I have a class that has virtual but non-pure declarations, like class A{ virtual void f(); }; Then is A still an abstract class? Do I have to have "virtual void f() = 0;"...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.