473,778 Members | 1,901 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Exceptions in destructors

I know that if an exception is thrown from a destructor while unwinding
the stack because of another exception, terminate() is called (FAQ
17.3). How exactly does this rule work? Is it acceptable to both throw
/and/ catch an exception inside a destructor, as in the following code?

struct Foo
{
void finalize()
{
throw 1.0;
}
~Foo()
{
try
{
finalize();
}
catch (double d)
{}
}
};

void bar()
{
Foo f;
throw 1;
}

int main()
{
try
{
bar();
}
catch (int i)
{}
return 0;
}

Rennie deGraaf
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.6 (GNU/Linux)

iD8DBQFGNVl6IvU 5mZP08HERAnkaAJ 9rODkY55YL/ON+PXYS0ImI2K78 3QCgzAwr
6zQzt0Hkj6h8KYR FfI/xYw8=
=H9qr
-----END PGP SIGNATURE-----

Apr 30 '07 #1
5 2084
Rennie deGraaf wrote:
I know that if an exception is thrown from a destructor while unwinding
the stack because of another exception, terminate() is called (FAQ
17.3). How exactly does this rule work? Is it acceptable to both throw
/and/ catch an exception inside a destructor, as in the following code?

[code redacted]
Yes, the restriction is that the exception may not escape the destructor.

Apr 30 '07 #2

On 4/29/07 7:50 PM, in article f1**********@en sb.cpsc.ucalgar y.ca, "Rennie
deGraaf" <de*****@cpsc.n o-processed-pork.ucalgary.c awrote:
I know that if an exception is thrown from a destructor while unwinding
the stack because of another exception, terminate() is called (FAQ
17.3). How exactly does this rule work? Is it acceptable to both throw
/and/ catch an exception inside a destructor, as in the following code?

struct Foo
{
void finalize()
{
throw 1.0;
}
~Foo()
{
try
{
finalize();
}
catch (double d)
{}
}
};
The runtime calls terminate() if - during exception processing - another
thrown exception "escapes" from the destructor in which it was thrown.

So as long as the thrown exception in the code above is caught before Foo's
destructor exits, then terminate() will not be called. Therefore the above
code is technically safe - but it is also fragile. Specifically, Foo's
destructor assumes that finalize() will only ever throw a double - but
through there is nothing in finalize()'s implementation that enforces such a
restriction - nor is there anything in Foo's destructor to check whether its
assumption about the type of finalize()'s thrown exceptions - remains valid
since the last time it checked.

Greg

Apr 30 '07 #3
Greg Herlihy wrote:


On 4/29/07 7:50 PM, in article f1**********@en sb.cpsc.ucalgar y.ca, "Rennie
deGraaf" <de*****@cpsc.n o-processed-pork.ucalgary.c awrote:
>I know that if an exception is thrown from a destructor while unwinding
the stack because of another exception, terminate() is called (FAQ
17.3). How exactly does this rule work? Is it acceptable to both throw
/and/ catch an exception inside a destructor, as in the following code?

struct Foo
{
void finalize()
{
throw 1.0;
}
~Foo()
{
try
{
finalize();
}
catch (double d)
{}
}
};
The runtime calls terminate() if - during exception processing - another
thrown exception "escapes" from the destructor in which it was thrown.

So as long as the thrown exception in the code above is caught before Foo's
destructor exits, then terminate() will not be called. Therefore the above
code is technically safe - but it is also fragile. Specifically, Foo's
destructor assumes that finalize() will only ever throw a double - but
through there is nothing in finalize()'s implementation that enforces such a
restriction - nor is there anything in Foo's destructor to check whether its
assumption about the type of finalize()'s thrown exceptions - remains valid
since the last time it checked.

Greg
In other words, I really should add throw specifiers, like this:

struct Foo
{
void finalize() throw(double)
{
throw 1.0;
}
~Foo() throw()
{
try
{
finalize();
}
catch (double d)
{}
}
};

I suppose that it would generally be a good idea to /always/ tag my
destructors with throw() unless I have a good reason to do otherwise?
For that matter, are there any circumstances where it would be safe to
throw an exception from a destructor?

Rennie deGraaf
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.6 (GNU/Linux)

iD8DBQFGNX7tIvU 5mZP08HERAu/9AJ0R26LkBLs6hV MjMAVsH181cMjTt gCfa7p2
jCaJy2cRDZA0JQg MQbdslt0=
=u7Mx
-----END PGP SIGNATURE-----

Apr 30 '07 #4
On Apr 29, 10:30 pm, Rennie deGraaf <degr...@cpsc.n o-processed-
pork.ucalgary.c awrote:
Greg Herlihy wrote:
On 4/29/07 7:50 PM, in article f13lhq$f3...@en sb.cpsc.ucalgar y.ca, "Rennie
deGraaf" <degr...@cpsc.n o-processed-pork.ucalgary.c awrote:
I know that if an exception is thrown from a destructor while unwinding
the stack because of another exception, terminate() is called (FAQ
17.3). How exactly does this rule work? Is it acceptable to both throw
/and/ catch an exception inside a destructor, as in the following code?
So as long as the thrown exception in the code above is caught before Foo's
destructor exits, then terminate() will not be called. Therefore the above
code is technically safe - but it is also fragile. Specifically, Foo's
destructor assumes that finalize() will only ever throw a double - but
through there is nothing in finalize()'s implementation that enforces such a
restriction - nor is there anything in Foo's destructor to check whether its
assumption about the type of finalize()'s thrown exceptions - remains valid
since the last time it checked.

In other words, I really should add throw specifiers, like this:

struct Foo
{
void finalize() throw(double)
{
throw 1.0;
}
~Foo() throw()
{
try
{
finalize();
}
catch (double d)
{}
}

};

I suppose that it would generally be a good idea to /always/ tag my
destructors with throw() unless I have a good reason to do otherwise?
Personally, I would not bother adding throw() to destructor
declarations. The time and effort for making such a change would
probably be better spent making sure that no destructor in the program
propagtes exceptions beyond its scope.

On the other hand, the exception specification for finalize() I would
keep. Even though C++ exception specifications are checked at runtime
and not compile-time - at least the double exception specification
serves to document a dependency on finalize()'s thrown exception type
- that previously was not documented anywhere.

For that matter, are there any circumstances where it would be safe to
throw an exception from a destructor?
Sure - in fact I would imagine that under most circumstances throwing
an exception from a destructor would be safe. The problem is that
there are always circumstances when throwing an exception from a
destructor is not safe - so what should the program do instead?

In other words, it does not make a lot of sense for a program to throw
an exception - unless it is safe to throw that exception every time
the program wants to throw it. Otherwise, the code paths of the
program need to split into two different error-handling paths - one
when the exception is thrown and another when it is not. So throwing
an exception from a destructor does not end up simplifying or
consolidating the program's error handling - instead the two execution
paths just makes the program more complicated for no reason.

Greg

Apr 30 '07 #5
On Apr 30, 7:30 am, Rennie deGraaf <degr...@cpsc.n o-processed-
pork.ucalgary.c awrote:

[...]
In other words, I really should add throw specifiers, like this:
struct Foo
{
void finalize() throw(double)
{
throw 1.0;
}
~Foo() throw()
{
try
{
finalize();
}
catch (double d)
{}
}
};
I suppose that it would generally be a good idea to /always/ tag my
destructors with throw() unless I have a good reason to do otherwise?
For that matter, are there any circumstances where it would be safe to
throw an exception from a destructor?
Opinions with regards to the utility of exception specifiers
vary:-). In general, there's pretty much a consensus that
specifiers which list possible exceptions are useless; the only
possible effect they can have is to result in slower code.
There's much less consensus regarding empty specifiers, e.g.
throw(); knowing that a function cannot throw is often important
information, both to the user and to the optimizer.

In practice, with regards to the reader, I would generally
expect a destructor not to throw, and any other function to
throw std::exception, or anything derived from it, unless
otherwise documented. Throwing from a destructor should be so
exceptional that not just the possibility itself, but the
justification and reasons behind it should be documented; an
exception specifier is not sufficient for this. And because
non-throwing destructors are so common, you can certainly not
count on the absense of a specifier on the destructor to signal
that it might throw. So from the human reader's point of view,
an exception specifier on a destructor doesn't really add any
useful information. Just the reverse is true for other
functions, however; in the absense of other documentation, you
should assume that the function can throw. And a simple
"throw()" is excellent documentation that it cannot. Unlike the
case for destructors, I don't think you normally have to justify
why the function doesn't throw; it's sufficient to document
clearly that it doesn't.

--
James Kanze (GABI Software) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Apr 30 '07 #6

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

Similar topics

16
5293
by: David Turner | last post by:
Hi all I noticed something interesting while testing some RAII concepts ported from C++ in Python. I haven't managed to find any information about it on the web, hence this post. The problem is that when an exception is raised, the destruction of locals appears to be deferred to program exit. Am I missing something? Is this behaviour by design? If so, is there any reason for it? The only rationale I can think of is to speed up...
7
9251
by: Michael Andersson | last post by:
Hi! Does the use of exception handling induce a performance penalty during the execution of non exception handling code? Regards, /Michael
9
3322
by: Magalie | last post by:
Hi! I've got a question concerning C++ exceptions, more precisely the stack unwinding when an exception occurs. We agree that when an exception is thrown, all objects that have destructors are "destructed" by calling the corresponding destructor. This is most often what is wanted. However,I have a special situation where this is NOT what I'd like to happen : indeed, i'd like to keep my objects living on the stack. Practically, this...
12
533
by: Siemel Naran | last post by:
(1) About std::exit. If I call this function, will the system call the destructors of all objects in the call stack. Eg. void f() { std::exit(1); } void g() { X x; f(); } Does the call in f() to std::exit invoke x.~X() in scope g()? (2) About signals and exceptions. Is it possible to throw an exception from
21
4443
by: mihai | last post by:
People say that is a bad technique to throw exception from constructors; and that the solution would be to create a function _create_ to initialize an object. What about copy constructors? How can we avoid throwing exceptions? If we already have an abject witch was initialized wit _create_ we will be forced to call create in copy constructor and to throw exceptions from it. Have a nice day,
59
4451
by: kk_oop | last post by:
Hi. I wanted to use exceptions to handle error conditions in my code. I think doing that is useful, as it helps to separate "go" paths from error paths. However, a coding guideline has been presented that says "Use conventional error-handling techniques rather than exception handling for straightforward local error processing in which a program is easily able to deal with its own errors." By "conventional error-handling," I believe...
15
426
by: Bernard | last post by:
Hi All, I am not sure if I should be asking this question on clc or clc++. Let me try on both. I hope that this is not too trivial for the brilliant minds over here. I know that OOP questions have been asked on clc before so it is probably OK. I am a newbie to C++. BS 3rd edition states: % The throw transfers control to a handler for exceptions .... %
40
3159
by: Mark P | last post by:
I'm implementing an algorithm and the computational flow is a somewhat deep. That is, fcn A makes many calls to fcn B which makes many calls to fcn C, and so on. The return value of the outermost fcn is a boolean and there are certain places within the inner functions where it may become apparent that the return value is false. In this case I'd like to halt the computation immediately and return false. My current approach is to have...
42
3048
by: Jon Harrop | last post by:
Why are exceptions in C++ ~6x slower than exceptions in OCaml? -- Dr Jon D Harrop, Flying Frog Consultancy Objective CAML for Scientists http://www.ffconsultancy.com/products/ocaml_for_scientists/index.html?usenet
0
9470
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 effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10127
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 tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
9923
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8957
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7475
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 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 a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6723
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5500
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4033
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
3
2865
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.