473,387 Members | 1,899 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,387 software developers and data experts.

Exception and derived destructor

Hi.

I have the following program:

class Papa
{
public:
Papa() {cout<<"Papa "<<endl;}
~Papa() { cout<<"~Papa "<<endl;}
};

class Son : public Papa
{
public:
Son() { m_pNumber=new int[100]; cout<<"Son "<<endl;}
~Son() { cout<<"~Son "<<endl;delete[] m_pNumber; }
private:
int* m_pNumber;
};

void main()
{
try{
Papa* p = new Son;

Son* a = new Son;
Son* b = a;

delete a;
delete b;
}
catch(...){
cout<<"Ooooooooops..."<<endl;
}
}

It is obvious that we get run time error when doing "delete b" since
we already deleted m_pNumber.

Why do we continue to Papa's destructor as well?

Thanks.
Jul 19 '05 #1
4 1935
Miri wrote:
Hi.

I have the following program:

class Papa
{
public:
Papa() {cout<<"Papa "<<endl;}
~Papa() { cout<<"~Papa "<<endl;}
};

class Son : public Papa
{
public:
Son() { m_pNumber=new int[100]; cout<<"Son "<<endl;}
~Son() { cout<<"~Son "<<endl;delete[] m_pNumber; }
private:
int* m_pNumber;
};

void main()
main() must return int.
{
try{
Papa* p = new Son;

Son* a = new Son;
Son* b = a;

delete a;
delete b;
}
catch(...){
cout<<"Ooooooooops..."<<endl;
}
}

It is obvious that we get run time error when doing "delete b" since
we already deleted m_pNumber.
That's not the reason, at least not the only one. You already deleted
the whole object. So b doesn't point to an object anymore. It points to
memory that doesn't belong to your program, and you are not allowed to
use delete on such a pointer.
Why do we continue to Papa's destructor as well?


What do you mean?

Jul 19 '05 #2

"Miri" <ko***@cs.biu.ac.il> wrote in message news:d0**************************@posting.google.c om...

It is obvious that we get run time error when doing "delete b" since
we already deleted m_pNumber.

Why do we continue to Papa's destructor as well?


When you invoke delete on b, you've now deleted the same value
twice. This is undefined behavior. What happens after that is
unpredictable (including any behavior of m_pNumber).

Further, while you don't actually do it, you have some other bugs
lurking.

Papa*p = new Son;

Assigns a pointer to a derived class (Son) object to the base class (Papa)
pointer. If you were to do
delete p;

You would have undefined behavior as Papa's destructor is not virtual.

Second, I think you may be confusing copying pointers and copying the
pointed to objects.

Son* b = a;
initializes the pointer a to the pointer b, it doesn't copy the objects.

If you were to do this with the objects:
Son b = *a;
or
Son* b = new Son(a)

you would have problems as you do not have a copy constructor that deals
with m_pNumber sensibly. The "rule of 3" says that if you write a destructor,
a copy constructor, or a copy-assignment operator, you probably need all
three.
Jul 19 '05 #3
Miri wrote:
class Papa
{
public:
Papa() {cout<<"Papa "<<endl;}
~Papa() { cout<<"~Papa "<<endl;}
};

class Son : public Papa
{
public:
Son() { m_pNumber=new int[100]; cout<<"Son "<<endl;}
~Son() { cout<<"~Son "<<endl;delete[] m_pNumber; }
private:
int* m_pNumber;
};

void main()
{
try{
Papa* p = new Son;

Son* a = new Son;
Son* b = a;

delete a;
delete b;
}
catch(...){
cout<<"Ooooooooops..."<<endl;
}
}

It is obvious that we get run time error when doing "delete b" since
we already deleted m_pNumber.
No, we don't get run time error. We get undefined behavior as a result
of an attempt to delete the same object twice. Anything can happen.
Why do we continue to Papa's destructor as well?


--
Best regards,
Andrey Tarasevich
Brainbench C and C++ Programming MVP

Jul 19 '05 #4
ko***@cs.biu.ac.il (Miri) wrote in message news:<d0**************************@posting.google. com>...
class Papa
{
public:
Papa() {cout<<"Papa "<<endl;}
~Papa() { cout<<"~Papa "<<endl;}
};

class Son : public Papa
{
public:
Son() { m_pNumber=new int[100]; cout<<"Son "<<endl;}
~Son() { cout<<"~Son "<<endl;delete[] m_pNumber; }
private:
int* m_pNumber;
};

void main()
ISO C++ requires that main return int (even if you don't want to
return a value).
{
try{
Papa* p = new Son;

Son* a = new Son;
Son* b = a;

delete a;
delete b;
}
catch(...){
cout<<"Ooooooooops..."<<endl;
}
}

It is obvious that we get run time error when doing "delete b" since

Why do we continue to Papa's destructor as well?


Deleting anything twice elicits undefined behavior, which could mean
any behavior at all. If you're lucky, the program will crash. If
you're not, your program may behave as if nothing happened (as is the
case here), or it may behave badly.

Furthermore, the operators delete and delete[] are not allowed to
throw an exception. If one diagnoses an error, beyond outputting an
error message, all it can do is ignore the error or abort the program.
Your implementation chose to ignore it.

The solution in your case is not to allow two pointers which might
share ownership of an object. My personal rule, whenever possible, is
to use "smart pointers" to manage single objects and std::vector to
manage arrays. That way, I don't actually delete anything myself, so
it's difficult to delete things too many -- or too few -- times.

- Shane
Jul 19 '05 #5

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

Similar topics

12
by: Dario | last post by:
The following simple program behaves differently in Windows and Linux . #include <stdexcept> #include <iostream> #include <string> using namespace std; class LogicError : public logic_error {...
4
by: Boogie El Aceitoso | last post by:
Hi, I have an exception class for winapi errors (returns a formated error mesage, usign ::GetLastError() et al, with what()). It looks like this: class WinapiException : public...
7
by: Douglas Peterson | last post by:
Take a look at this code, it looks funny as its written to be as short as possible: -- code -- struct Base { ~Base() { *((char*)0) = 0; } }; struct Derived : public Base
3
by: Pierre Rouleau | last post by:
The std::exception class defined in the Standard C++ <exception> header specifies that the constructors could throw any exception becuase they do not have a throw() specification. Why is that? ...
9
by: Jeff Louie | last post by:
In C# (and C++/cli) the destructor will be called even if an exception is thrown in the constructor. IMHO, this is unexpected behavior that can lead to an invalid system state. So beware! ...
8
by: Kannan | last post by:
Some amount of memory is allocated inside the Base Constructor using new. During the construction of a derived object an exception occurred in the constructor of the derived class. Will the...
3
by: Nindi73 | last post by:
Hi, I am in need of a deep copy smart pointer (Boost doesn't provide one) which doesnt require the contained types to have a virtual copy constructor. I wrote a smart pointer class that I think...
5
by: Bushido Hacks | last post by:
I think this message got lost the first time I sent it, so I'm reposting it. I need a little help with Destructors. Suppose I created a multidimmensional array in a Base class that was also...
4
by: amphetaman | last post by:
If I derive my own Exception class from std::runtime_error, do I have to write the destructor even if its body is empty? #include <stdexcept> class Exception : public std::runtime_error {...
11
by: Peter Jansson | last post by:
Dear newsgroup, In the following code, it looks as though the exception thrown in the constructor is not caught properly. I get this output: ---- standard output ---- Base() constructor....
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

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.