By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
464,486 Members | 1,199 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 464,486 IT Pros & Developers. It's quick & easy.

Can I tell in the destructor if an exception occured ?

P: n/a
Hy

I have destructors that do some functional work in the program flow.
The problem is destructors should only be used for clean-up, because
exceptions might rise at any time, and destructors will be called for
clean-up only.

So how can I tell, from within the destructor, if the call has been made as
part of normal flow of control and the destructor can play its functional
role, or if the call has been made as a result of an exception and the
destructor should rollback, abort and clean up ?

What if I need to propagate this state to other destructors that are called
before the current destructor returns, so that the other destructors can
take appropiate action ?

How come there is no real way to comunicate with the destructors ?
Constructors I can choose, I can pass parameters to, but for destructors ?

Thank you
"Timothy Madden"
Romania
Jul 22 '05 #1
Share this Question
Share on Google+
16 Replies

P: n/a
On Wed, 17 Nov 2004 12:47:27 +0200, "Timothy Madden"
<ba****@rmv.spam.home.ro> wrote:
Hy

I have destructors that do some functional work in the program flow.
The problem is destructors should only be used for clean-up, because
exceptions might rise at any time, and destructors will be called for
clean-up only.

So how can I tell, from within the destructor, if the call has been made as
part of normal flow of control and the destructor can play its functional
role, or if the call has been made as a result of an exception and the
destructor should rollback, abort and clean up ?

What if I need to propagate this state to other destructors that are called
before the current destructor returns, so that the other destructors can
take appropiate action ?

How come there is no real way to comunicate with the destructors ?
Constructors I can choose, I can pass parameters to, but for destructors ?

Thank you
"Timothy Madden"
Romania


uncaught_exception() will tell you. But many compilers apparently have
had trouble with it until only recently, e.g. GCC 3.4 was reported to
handle it OK, whereas earlier versions did not.

--
Bob Hairgrove
No**********@Home.com
Jul 22 '05 #2

P: n/a

"Bob Hairgrove" <in*****@bigfoot.com> wrote in message
news:ei********************************@4ax.com...
On Wed, 17 Nov 2004 12:47:27 +0200, "Timothy Madden"
<ba****@rmv.spam.home.ro> wrote:
Hy

I have destructors that do some functional work in the program flow.
The problem is destructors should only be used for clean-up, because
exceptions might rise at any time, and destructors will be called for
clean-up only.

So how can I tell, from within the destructor, if the call has been made aspart of normal flow of control and the destructor can play its functional
role, or if the call has been made as a result of an exception and the
destructor should rollback, abort and clean up ?

What if I need to propagate this state to other destructors that are calledbefore the current destructor returns, so that the other destructors can
take appropiate action ?

How come there is no real way to comunicate with the destructors ?
Constructors I can choose, I can pass parameters to, but for destructors ?
Thank you
"Timothy Madden"
Romania


uncaught_exception() will tell you. But many compilers apparently have
had trouble with it until only recently, e.g. GCC 3.4 was reported to
handle it OK, whereas earlier versions did not.

I tryed it on my platform (80x86, Win2000, VC++ 6.0 SP5), it doesn't work
:(
Anything else I can do ?
Anything ?

Thank you
"Timothy Madden"
Romania
Jul 22 '05 #3

P: n/a
On Wed, 17 Nov 2004 14:02:21 +0200, "Timothy Madden"
<ba****@rmv.spam.home.ro> wrote:
uncaught_exception() will tell you. But many compilers apparently have
had trouble with it until only recently, e.g. GCC 3.4 was reported to
handle it OK, whereas earlier versions did not.

I tryed it on my platform (80x86, Win2000, VC++ 6.0 SP5), it doesn't work
:(
Anything else I can do ?


Yes. Update your compiler to MSVC++ 7.1 ... quickly. Version 6 is
broken in many ways. BTW you can download the command-line version for
free from the MS website, called "MS Visual C++ Toolkit". The drawback
is that they only provide static libraries to link with the C/C++
runtime libraries. But otherwise, it is fully functional and you can
use code optimizations.

Unfortunately, I have never had occasion to use uncaught_exception
myself yet, so I cannot say whether it works with this compiler or
not.

--
Bob Hairgrove
No**********@Home.com
Jul 22 '05 #4

P: n/a
Timothy Madden wrote:
Hy

I have destructors that do some functional work in the program flow.
The problem is destructors should only be used for clean-up, because
exceptions might rise at any time, and destructors will be called for
clean-up only.
seems to me like a strange design
why not do the functional work out of the destructor?
as you say, destructors should be called for cleanup (e.g. cleaning up a
socket, call other object's destructor, ...) , not for common logic in your
program. you can put the logic before you're object is going out of scope
(and the destructor will be called) (or before a manual call to the
destructor)

So how can I tell, from within the destructor, if the call has been made
as part of normal flow of control and the destructor can play its
functional role, or if the call has been made as a result of an exception
and the destructor should rollback, abort and clean up ?

What if I need to propagate this state to other destructors that are
called before the current destructor returns, so that the other
destructors can take appropiate action ?
a destructor should clean-up resources that this object hold. that's the
only purpose. if this object is destroyed, ask yourself which other objects
need to be destroyed.
if an error occurs, you can catch the exception and do whatever needs to be
done in the exception handler (possibly destroying resources). if no error
occurs, just do what you mean to do according to normal flow of execution.
remember that the destructor should never contain "normal program
flow"-code.
How come there is no real way to comunicate with the destructors ?
Constructors I can choose, I can pass parameters to, but for destructors ?

Thank you
"Timothy Madden"
Romania


Jul 22 '05 #5

P: n/a

"slurper" <sl*********@hotmail.com> wrote in message
news:41***********************@news.skynet.be...
Timothy Madden wrote:
Hy

I have destructors that do some functional work in the program flow.
The problem is destructors should only be used for clean-up, because
exceptions might rise at any time, and destructors will be called for
clean-up only.
seems to me like a strange design
why not do the functional work out of the destructor?
as you say, destructors should be called for cleanup (e.g. cleaning up a
socket, call other object's destructor, ...) , not for common logic in

your program. you can put the logic before you're object is going out of scope
(and the destructor will be called) (or before a manual call to the
destructor)

Yes it is, I have no better ideea. However if anyone knows please tell me
what could be the solution.

I wrote a class used to fill in records in tables from a relational
database.
Records in a related table should be updated and commited in the database
only after the coresponding record in the master table, to respect
referential integrity. The purpose of the class is to allow the application
to fill the tables in whatever order it wishes, provided that when everey
record is done, overall referential integrity is respected.

The strategy is to buffer update requests on the related table until the
master table is updated, when the related updates are also flushed/commited.

The objects of the class just fill in filelds in the record. The update
happens automaticaly in the destructor, if if is possible, followed by
updates of related records. If it is not possible (the master table is not
ready yet) then the destructor buffers the update command and lets the
destructor of the master table do the job when it gets called.

Someone has a better way to do this without destructors ?

Thank you
"Timothy Madden"
Romania
Jul 22 '05 #6

P: n/a
Timothy Madden wrote:

"slurper" <sl*********@hotmail.com> wrote in message
news:41***********************@news.skynet.be...
Timothy Madden wrote:
> Hy
>
> I have destructors that do some functional work in the program flow.
> The problem is destructors should only be used for clean-up, because
> exceptions might rise at any time, and destructors will be called for
> clean-up only.
seems to me like a strange design
why not do the functional work out of the destructor?
as you say, destructors should be called for cleanup (e.g. cleaning up a
socket, call other object's destructor, ...) , not for common logic in

your
program. you can put the logic before you're object is going out of scope
(and the destructor will be called) (or before a manual call to the
destructor)

Yes it is, I have no better ideea. However if anyone knows please tell me
what could be the solution.

I wrote a class used to fill in records in tables from a relational
database.
Records in a related table should be updated and commited in the database
only after the coresponding record in the master table, to respect
referential integrity. The purpose of the class is to allow the
application to fill the tables in whatever order it wishes, provided that
when everey record is done, overall referential integrity is respected.

The strategy is to buffer update requests on the related table until the
master table is updated, when the related updates are also
flushed/commited.

The objects of the class just fill in filelds in the record. The update
happens automaticaly in the destructor, if if is possible, followed by
updates of related records. If it is not possible (the master table is not
ready yet) then the destructor buffers the update command and lets the
destructor of the master table do the job when it gets called.

Someone has a better way to do this without destructors ?


if i understand well: why not first write the logic to update the master
table and then write the logic to update the table which references the
master table? (in a sequential manner) you can combine both operations on
the database in a transaction if your database management system supports
it (but that's not necessary per se). why do you want to put that in a
destructor?

Thank you
"Timothy Madden"
Romania


Jul 22 '05 #7

P: n/a
On Wed, 17 Nov 2004 16:37:57 +0200, "Timothy Madden"
<ba****@rmv.spam.home.ro> wrote:
I wrote a class used to fill in records in tables from a relational
database.
Records in a related table should be updated and commited in the database
only after the coresponding record in the master table, to respect
referential integrity. The purpose of the class is to allow the application
to fill the tables in whatever order it wishes, provided that when everey
record is done, overall referential integrity is respected.

The strategy is to buffer update requests on the related table until the
master table is updated, when the related updates are also flushed/commited.

The objects of the class just fill in filelds in the record. The update
happens automaticaly in the destructor, if if is possible, followed by
updates of related records. If it is not possible (the master table is not
ready yet) then the destructor buffers the update command and lets the
destructor of the master table do the job when it gets called.

Someone has a better way to do this without destructors ?


Perhaps. It would depend on the RDBMS you have.

In general, such multi-table updates are best wrapped in a transaction
which can be committed or rolled back as a whole. If you indeed have a
referential DBMS, then you should have foreign key constraints in
place, otherwise it is very dangerous to do what you are trying to do
(i.e. enforce referential integrity in the application instead of in
the database) because of the danger of inconsistent data when
something goes wrong.

--
Bob Hairgrove
No**********@Home.com
Jul 22 '05 #8

P: n/a
"Timothy Madden" <ba****@rmv.spam.home.ro> wrote in message news:<30*************@uni-berlin.de>...
I have destructors that do some functional work in the program flow.
The problem is destructors should only be used for clean-up, because
exceptions might rise at any time, and destructors will be called for
clean-up only.


Um. Not sure I'm following what you mean. Can you give some more
description of what you mean by "functional work in the program
flow?" Because destructors *should* only get called for cleanup.
(And resource deallocation, and such like.) So, I'm thinking
you've done something pretty strange.
Socks
Jul 22 '05 #9

P: n/a

"Bob Hairgrove" <in*****@bigfoot.com> wrote in message
news:71********************************@4ax.com...
On Wed, 17 Nov 2004 16:37:57 +0200, "Timothy Madden"
<ba****@rmv.spam.home.ro> wrote:
I wrote a class used to fill in records in tables from a relational
database.
Records in a related table should be updated and commited in the database
only after the coresponding record in the master table, to respect
referential integrity. The purpose of the class is to allow the applicationto fill the tables in whatever order it wishes, provided that when everey
record is done, overall referential integrity is respected.

The strategy is to buffer update requests on the related table until the
master table is updated, when the related updates are also flushed/commited.
The objects of the class just fill in filelds in the record. The update
happens automaticaly in the destructor, if if is possible, followed by
updates of related records. If it is not possible (the master table is notready yet) then the destructor buffers the update command and lets the
destructor of the master table do the job when it gets called.

Someone has a better way to do this without destructors ?


Perhaps. It would depend on the RDBMS you have.

In general, such multi-table updates are best wrapped in a transaction
which can be committed or rolled back as a whole. If you indeed have a
referential DBMS, then you should have foreign key constraints in
place, otherwise it is very dangerous to do what you are trying to do
(i.e. enforce referential integrity in the application instead of in
the database) because of the danger of inconsistent data when
something goes wrong.

I can't say what RDBMS I have because I do not relay on one of them.
I can change the DBMS as this choice does not affect the application and I
currently am not satisfied with the one I use (Access 2000).
Transaction support is a property of the DBMS so there isn't much I can do
about it in the application. I have set foreign key constraints in the
database
and I try to follow them in the app (not enforce them); this is way I've
done
my class.

Thank you
"Timothy Madden"
Romania
Jul 22 '05 #10

P: n/a

"slurper" <sl*********@hotmail.com> wrote in message
news:41***********************@news.skynet.be...
Timothy Madden wrote:
[ ... ] I wrote a class used to fill in records in tables from a relational
database.
Records in a related table should be updated and commited in the database only after the coresponding record in the master table, to respect
referential integrity. The purpose of the class is to allow the
application to fill the tables in whatever order it wishes, provided that when everey record is done, overall referential integrity is respected.

The strategy is to buffer update requests on the related table until the
master table is updated, when the related updates are also
flushed/commited.

The objects of the class just fill in filelds in the record. The update
happens automaticaly in the destructor, if if is possible, followed by
updates of related records. If it is not possible (the master table is not ready yet) then the destructor buffers the update command and lets the
destructor of the master table do the job when it gets called.

Someone has a better way to do this without destructors ?


if i understand well: why not first write the logic to update the master
table and then write the logic to update the table which references the
master table? (in a sequential manner) you can combine both operations on
the database in a transaction if your database management system supports
it (but that's not necessary per se). why do you want to put that in a
destructor?

There is no difference between master tables and related tables. Any table
can be master and related in the same time. There is only one class. The
tables relationship view in the database shows something like a big tree. I
use destructors so that I can provide data to be entered in the tables in
any order the app needs, and on the destructor the decision is made about
whether the table can be immediatly updated or should wait for the update on
some master table.

Thank you
"Timothy Madden"
Romania
Jul 22 '05 #11

P: n/a

<pu*********@hotmail.com> wrote in message
news:c7**************************@posting.google.c om...
"Timothy Madden" <ba****@rmv.spam.home.ro> wrote in message

news:<30*************@uni-berlin.de>...
I have destructors that do some functional work in the program flow.
The problem is destructors should only be used for clean-up, because
exceptions might rise at any time, and destructors will be called for
clean-up only.


Um. Not sure I'm following what you mean. Can you give some more
description of what you mean by "functional work in the program
flow?" Because destructors *should* only get called for cleanup.
(And resource deallocation, and such like.) So, I'm thinking
you've done something pretty strange.
Socks


Yes, but you may find cases when the destructors have other functions in the
normal
flow of control. For example a class for a windows on screen in a GUI should
of course close the window in the destructor if it has not been already
closed. Or a class for a buffered stream should of course flush the buffer
and close the stream. Flushing a buffer on disk may cause an exception,
after the first attempt to write in the buffer has already generated
exceptions.

Think of a class that wrapps some generic process, that in normal usage just
collects a lot of input for the process. Only after the desctructor gets
called can you be sure no more input is going to be delinvered for the
process and in the destructor you can now start and perform the process to
its finish.

Thank you
"Timothy Madden"
Romania
Jul 22 '05 #12

P: n/a
"Timothy Madden" <ba****@rmv.spam.home.ro> wrote in message news:<30*************@uni-berlin.de>...

[snip]
Yes, but you may find cases when the destructors have other functions in the
normal
flow of control. For example a class for a windows on screen in a GUI should
of course close the window in the destructor if it has not been already
closed. Or a class for a buffered stream should of course flush the buffer
and close the stream. Flushing a buffer on disk may cause an exception,
after the first attempt to write in the buffer has already generated
exceptions.

Think of a class that wrapps some generic process, that in normal usage just
collects a lot of input for the process. Only after the desctructor gets
called can you be sure no more input is going to be delinvered for the
process and in the destructor you can now start and perform the process to
its finish.

Thank you
"Timothy Madden"
Romania


struct Main {
// allocate pImpl_;
Main();
// does all the program work
~Main();
private:
struct Impl;
Impl* pImpl_;
};

int main()
{
Main m;
return 0;
}

If this looks strange to you: I agree. It's just taking your logic to
an extreme.

Let's get more serious now:

Don't be afraid of specifying requirements to the user of your DB interface.
+ If you write data to me (the DB interface) then you have to call
flush().
+ If you forget to do this, I will do it in my destructor. However please
be aware that any errors will be remain unhandled and you have no
way to find out if the data was actually written to the DB.
Stephan Brönnimann
br****@osb-systems.com
Open source rating and billing engine for communication networks.
Jul 22 '05 #13

P: n/a
"Timothy Madden" <ba****@rmv.spam.home.ro> wrote in message news:<30*************@uni-berlin.de>...
[discussion of what dtors should do snipped]
Yes, but you may find cases when the destructors have other functions in the
normal
flow of control. For example a class for a windows on screen in a GUI should
of course close the window in the destructor if it has not been already
closed. Or a class for a buffered stream should of course flush the buffer
and close the stream. Flushing a buffer on disk may cause an exception,
after the first attempt to write in the buffer has already generated
exceptions.
In that case, the flush operation should catch the exception and handle
it appropriately. If the dtor *can't* deal with the exception, then you
should reconsider the design of your system so that either the exception
can't be thrown in the dtor or the dtor *can* deal with the exception.

For example, if the data stream belongs to the object, then the object
should do whatever is appropriate about errors on the stream. If the
data stream does *not* belong to the object, it should not be doing
the closing ops on the stream.

If a resource requires some extraordinary care at shutdown, then
you may want to rethink the notion of using the standard dtor
mechanism. For example, if you were dealing with some sensitive
hardware that required some special actions to be guaranteed to
take place on shutdown, you may want to do something very special
about its control from code. But such situations would be quite rare.
Think of a class that wrapps some generic process, that in normal usage just
collects a lot of input for the process. Only after the desctructor gets
called can you be sure no more input is going to be delinvered for the
process and in the destructor you can now start and perform the process to
its finish.


Um. I'm pretty sure I'd never do things that way. If the data is going
to be unsolicited, user input for example, you need to have some way
of polling. And when you are done polling, you shut things down and
*don't* accept any more input. If, in the dtor, some "orphaned"
input has been received, then you dispose of it appropriately.
Socks
Jul 22 '05 #14

P: n/a
"Timothy Madden" <ba****@rmv.spam.home.ro> wrote in message news:<30*************@uni-berlin.de>...

So how can I tell, from within the destructor, if the call has been made as
part of normal flow of control and the destructor can play its functional
role, or if the call has been made as a result of an exception and the
destructor should rollback, abort and clean up ?


Don't know exactly what you mean but can you do something like:

class Foo{
public:
Foo() : caughtException(false){}
void hasException(bool b){caughtException = b;}
~Foo(){
if(caughtException)
// has exception
else
// normal exit
}
private:
bool caughtException;
};

later:

Foo f;
try{
throw 1;
}catch(int){
f.hasException(true);
}

not sure if that's what you want.
Jul 22 '05 #15

P: n/a
"Timothy Madden" <ba****@rmv.spam.home.ro> wrote in message
news:<30*************@uni-berlin.de>...
I have destructors that do some functional work in the program flow.
The problem is destructors should only be used for clean-up, because
exceptions might rise at any time, and destructors will be called for
clean-up only.


Contrary to most other respondents, I don't think your design is so
bizarre. However, there is a "better" solution. Instead of coding
the "normal functional" work in the destructor, put the normal
funcitonal work in a "finalizeAndDelete()" member function.

The finalizeAndDelete() member function can do the writing of the
objects to the DBMS and check the ordering constraints, calling the
appropriate finalizeAndDelete() members of the other tables as needed,
after it has done all the work then, it cleans up the object setting
it into a state ssaying that it has been successfully written, and as
the very last thing deletes the object itself. Strictly speaking, you
don't need to delete the object in the function, but you probably wish
to to prevent the object from getting "re-used" by later changes in
the logic.

The destructor then can check to see if the object has been
succesfully written (i.e. finalizeAndDelete() was called on it) or not
and do the appropriate clean up to handle aborts etc.

It amy seem simpler to put the code which belongs in the member
function finalizeAndDelete() in the destructor, since C++ assures one
that the destructor will be called. However, in your case where you
have exception issues, keeping that code out of the destructor will
lead to a simpler solution overall. Yes, you have to assure that
finalizeAndDelete is called. HOwever, that is actually not such an
onerous requirement.

Hope this helps,
-Chris

************************************************** ***************************
Chris Clark Internet : co*****@world.std.com
Compiler Resources, Inc. Web Site : http://world.std.com/~compres
23 Bailey Rd voice : (508) 435-5016
Berlin, MA 01503 USA fax : (978) 838-0263 (24 hours)
------------------------------------------------------------------------------
Jul 22 '05 #16

P: n/a
I wrote the following rubish:
It may seem simpler to put the code which belongs in the member
function finalizeAndDelete() in the destructor, since C++ assures one
that the destructor will be called.


Of course, C++ doesn't guarantee that destructors are called for
objects on the "heap" and other circumstances. Only stack based
objects have nice destructor properties and even there, if one does
things which make copies, the rules can get more complex that I want
to deal with.

However, normal C++ coding practices often involve approaches to make
certain that desructors are called at the appropriate times (by having
classes destroy the objects "owned" by them and related techniques).
The same techniques can be applied to "finalizeAndDelete()" member
function calls and that was my point.

My apologies for the error I made above. I hope no one gets misled by
it.

Hope this helps,
-Chris

************************************************** ***************************
Chris Clark Internet : co*****@world.std.com
Compiler Resources, Inc. Web Site : http://world.std.com/~compres
23 Bailey Rd voice : (508) 435-5016
Berlin, MA 01503 USA fax : (978) 838-0263 (24 hours)
------------------------------------------------------------------------------
Jul 22 '05 #17

This discussion thread is closed

Replies have been disabled for this discussion.