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

Detect if my destructor is called by unwinding through an exception?

P: n/a
I have a simple class that verifies some data between the beginning and the
end of a function:

class Verify
{
Verify() { note the data value }
~Verify() { check if data value is the same as we noted }
};

void foo()
{
Verify _v;
...
throw SomeException; // test can fail because _v is destroyed
'prematurely'
...
};

~Verify() just makes an assertion to warn me that I've done something wrong
in the function body.
If the exception occurs, the verification is no longer relevant.
Is there some way to detect that I'm (~Verify()) being destroyed by an
exception rather than the end of scope?
i.e.
~Verify()
{ if (!exception) assert(...); }

I know I could add another variable into the function, or set some member of
Verify before I throw, but that defeats the point of using the Verify class
as a simple way to test the integrity of the function.
Jul 23 '05 #1
Share this Question
Share on Google+
11 Replies


P: n/a

"Douglas Peterson" <Te******@nospam.msn.com> wrote in message
news:qN********************@comcast.com...
I have a simple class that verifies some data between the beginning and the end of a function:
Why not keep data constant in the function instead? Or implement a verify()
method in your data class otherwise?

class Verify
{
Verify() { note the data value }
~Verify() { check if data value is the same as we noted }
};

void foo()
{
Verify _v;
...
throw SomeException; // test can fail because _v is destroyed
'prematurely'
...
};

~Verify() just makes an assertion to warn me that I've done something wrong in the function body.
If the exception occurs, the verification is no longer relevant.
Is there some way to detect that I'm (~Verify()) being destroyed by an
exception rather than the end of scope?
To verify that Verify zapped your destructor? You should rethink the design
here. A constructor should be performing construction, not verification.
Ditto for the destructor. Throwing exceptions from a ctor or d~tor is a good
example of a_big_no_no.
i.e.
~Verify()
{ if (!exception) assert(...); }

I know I could add another variable into the function, or set some member of Verify before I throw, but that defeats the point of using the Verify class as a simple way to test the integrity of the function.


You aren't testing the integrity of the function, you are testing the data's
integrity.
Jul 23 '05 #2

P: n/a
It's just a assertion to verify that my stack (not the program stack) is
left in the same state it was in when the function began as a sanity check
for when/if the code gets modified.

class Verify
{
public:
Verify() { m_stackDepth = getStackDepth(); }
~Verify() { assert(m_stackDepth == getStackDepth(); }
int m_stackDepth;
};

That's the whole of it. I can put one line at the beginning of every
function that manipulates the stack:

void foo()
{
Verify _verify;
...
}

Simple as pie.

Obviously I could write:

void foo()
{
int _stackDepth = getStackDepth();
...
assert(_stackDepth == getStackDepth());
}

That might seem to solve the problem (since the assertion would be skipped
by a throw), but many of the roughly 60 functions that use this have
alternate return paths. The best solution IMO was to toss the check into a
class object.

If a throw occurs during execution of the function, the stack depth (again
keep in mind we're not talking about the program stack) being out of sync is
no longer relevant, the entire stack gets destroyed as a result of the error
condition.

I can just leave it as is of course, but it's annoying getting the assertion
when it has no meaning.

"codigo" <co****@codigo.trap.com> wrote in message
news:We*****************@news20.bellglobal.com...

"Douglas Peterson" <Te******@nospam.msn.com> wrote in message
news:qN********************@comcast.com...
I have a simple class that verifies some data between the beginning and

the
end of a function:


Why not keep data constant in the function instead? Or implement a
verify()
method in your data class otherwise?

class Verify
{
Verify() { note the data value }
~Verify() { check if data value is the same as we noted }
};

void foo()
{
Verify _v;
...
throw SomeException; // test can fail because _v is destroyed
'prematurely'
...
};

~Verify() just makes an assertion to warn me that I've done something

wrong
in the function body.
If the exception occurs, the verification is no longer relevant.
Is there some way to detect that I'm (~Verify()) being destroyed by an
exception rather than the end of scope?


To verify that Verify zapped your destructor? You should rethink the
design
here. A constructor should be performing construction, not verification.
Ditto for the destructor. Throwing exceptions from a ctor or d~tor is a
good
example of a_big_no_no.
i.e.
~Verify()
{ if (!exception) assert(...); }

I know I could add another variable into the function, or set some member

of
Verify before I throw, but that defeats the point of using the Verify

class
as a simple way to test the integrity of the function.


You aren't testing the integrity of the function, you are testing the
data's
integrity.

Jul 23 '05 #3

P: n/a
"Douglas Peterson" <Tergi...@nospam.msn.com> wrote:
If the exception occurs, the verification is no longer relevant.
Is there some way to detect that I'm (~Verify()) being destroyed by an exception rather than the end of scope? i.e.
~Verify()
{ if (!exception) assert(...); }


Try uncaught_exception() (though this function is deemed to be
unelegant).

A.C.

Jul 23 '05 #4

P: n/a
Douglas Peterson wrote:
<skip>
If the exception occurs, the verification is no longer
relevant. Is there some way to detect that I'm (~Verify())
being destroyed by an exception rather than the end of scope?


std::uncaught_exception() (from header <exception>) returns true
if an unhandled exception exists. I guess this is the case you're
interested in.

Borland C++Builder 6 and MS VS.NET 2003 do contain this function.
Jul 23 '05 #5

P: n/a

"Douglas Peterson" <Te******@nospam.msn.com> skrev i en meddelelse
news:qN********************@comcast.com...
I have a simple class that verifies some data between the beginning and the
end of a function:

class Verify
{
Verify() { note the data value }
~Verify() { check if data value is the same as we noted }
};

void foo()
{
Verify _v;
...
throw SomeException; // test can fail because _v is destroyed
'prematurely'
...
};

~Verify() just makes an assertion to warn me that I've done something
wrong in the function body.
If the exception occurs, the verification is no longer relevant.
Is there some way to detect that I'm (~Verify()) being destroyed by an
exception rather than the end of scope?
i.e.
~Verify()
{ if (!exception) assert(...); }

I know I could add another variable into the function, or set some member
of Verify before I throw, but that defeats the point of using the Verify
class as a simple way to test the integrity of the function.


You can't. Some advise you to use uncaught_exception, but this will not work
in the general case as your function might be called as a result of
unwinding an exception. (Meaning you will not get your check done in that
case). Still, I do not understand why you do not care about consistent
objects after an exception. If you allow bad objects in case of exceptions,
then you risk having them all the time.

/Peter
Jul 23 '05 #6

P: n/a

"Douglas Peterson" <Te******@nospam.msn.com> wrote in message
news:Jf********************@comcast.com...
It's just a assertion to verify that my stack (not the program stack) is
left in the same state it was in when the function began as a sanity check
for when/if the code gets modified.

class Verify
{
public:
Verify() { m_stackDepth = getStackDepth(); }
~Verify() { assert(m_stackDepth == getStackDepth(); }
int m_stackDepth;
};

That's the whole of it. I can put one line at the beginning of every
function that manipulates the stack:

void foo()
{
Verify _verify;
...
}

Simple as pie.

Obviously I could write:

void foo()
{
int _stackDepth = getStackDepth();
...
assert(_stackDepth == getStackDepth());
}

That might seem to solve the problem (since the assertion would be skipped
by a throw), but many of the roughly 60 functions that use this have
alternate return paths. The best solution IMO was to toss the check into a
class object.


Instead of inserting an object inside your functions, how about calling your
functions inside a wrapper function? If your function signatures are the
same (or at least if there are a limited number of them), then this should
work. Something like this:

StackCheckVoid( foovoid() );
StackCheckVoid( barvoid() );
int x = StackCheckInt( fooint() ); // where foo int returns an int

Or, even a template to do something similar?

-Howard


Jul 23 '05 #7

P: n/a
That's a very good solution--far too obvious for an idiot such as I - doh!

I wish I had thought of it before I started.

They are all callback functions that have the exact same signiture, though I
don't see how that might help. There is no way to forward the 'real' address
through a check function. I'll have to create a wrapper for each and change
every reference in the source.

Thanks Howard.
"Howard" <al*****@hotmail.com> wrote in message
news:yj*********************@bgtnsc05-news.ops.worldnet.att.net...

"Douglas Peterson" <Te******@nospam.msn.com> wrote in message
news:Jf********************@comcast.com...
It's just a assertion to verify that my stack (not the program stack) is
left in the same state it was in when the function began as a sanity
check for when/if the code gets modified.

class Verify
{
public:
Verify() { m_stackDepth = getStackDepth(); }
~Verify() { assert(m_stackDepth == getStackDepth(); }
int m_stackDepth;
};

That's the whole of it. I can put one line at the beginning of every
function that manipulates the stack:

void foo()
{
Verify _verify;
...
}

Simple as pie.

Obviously I could write:

void foo()
{
int _stackDepth = getStackDepth();
...
assert(_stackDepth == getStackDepth());
}

That might seem to solve the problem (since the assertion would be
skipped by a throw), but many of the roughly 60 functions that use this
have alternate return paths. The best solution IMO was to toss the check
into a class object.


Instead of inserting an object inside your functions, how about calling
your functions inside a wrapper function? If your function signatures are
the same (or at least if there are a limited number of them), then this
should work. Something like this:

StackCheckVoid( foovoid() );
StackCheckVoid( barvoid() );
int x = StackCheckInt( fooint() ); // where foo int returns an int

Or, even a template to do something similar?

-Howard


Jul 23 '05 #8

P: n/a
In message <yj*********************@bgtnsc05-news.ops.worldnet.att.net>,
Howard <al*****@hotmail.com> writes

"Douglas Peterson" <Te******@nospam.msn.com> wrote in message
news:Jf********************@comcast.com...
It's just a assertion to verify that my stack (not the program stack) is
left in the same state it was in when the function began as a sanity check
for when/if the code gets modified.

[...]

Instead of inserting an object inside your functions, how about calling your
functions inside a wrapper function? If your function signatures are the
same (or at least if there are a limited number of them), then this should
work. Something like this:

StackCheckVoid( foovoid() );


Ahem. I don't think you want to call foovoid() just yet :-(

Try this: StackCheckVoid(foovoid);

--
Richard Herring
Jul 23 '05 #9

P: n/a

"Richard Herring" <ju**@[127.0.0.1]> wrote in message
news:L2**************@baesystems.com...
In message <yj*********************@bgtnsc05-news.ops.worldnet.att.net>,
Howard <al*****@hotmail.com> writes

"Douglas Peterson" <Te******@nospam.msn.com> wrote in message
news:Jf********************@comcast.com...
It's just a assertion to verify that my stack (not the program stack) is
left in the same state it was in when the function began as a sanity
check
for when/if the code gets modified.


[...]

Instead of inserting an object inside your functions, how about calling
your
functions inside a wrapper function? If your function signatures are the
same (or at least if there are a limited number of them), then this should
work. Something like this:

StackCheckVoid( foovoid() );


Ahem. I don't think you want to call foovoid() just yet :-(

Try this: StackCheckVoid(foovoid);


D'oh! Quite correct, that's what I meant.
Thanks,
-Howard

Jul 23 '05 #10

P: n/a

"Douglas Peterson" <Te******@nospam.msn.com> wrote in message
news:Pa********************@comcast.com...
Instead of inserting an object inside your functions, how about calling
your functions inside a wrapper function? If your function signatures
are the same (or at least if there are a limited number of them), then
this should work. Something like this:

StackCheckVoid( foovoid() );
StackCheckVoid( barvoid() );
int x = StackCheckInt( fooint() ); // where foo int returns an int

Or, even a template to do something similar?

-Howard
That's a very good solution--far too obvious for an idiot such as I - doh!

I wish I had thought of it before I started.

They are all callback functions that have the exact same signiture, though
I don't see how that might help. There is no way to forward the 'real'
address through a check function. I'll have to create a wrapper for each
and change every reference in the source.


As Richard pointed out, I made a mistake there. There shouldn't be
parentheses on the function parameters in my example. But there shouldn't
be a problem passing a function as a parameter. It's easiest if you make a
typedef (alias) for the function type, then use that new type as the
StackCheck function's parameter type. Look up function pointers in your
favorite book.

-Howard

Jul 23 '05 #11

P: n/a
They are callback functions of another library.

SomeLibraryRegisterForCallback1(foo);

int foo(somelibrarytype * ptr)
{ // gets called by the library in response to some event
}

There is no way to have foo (in the example above) be a generic StackCheck
because there is no way to forward the address of foo through that call.
Although I have access to the object being passed in, I have no way of
knowing which event is being fired except by registering different function
addresses for different events (without changing the library source of
course). So I have to wrap every one of them:

SomeLibraryRegisterForCallback1(foocheck);
int foocheck(somelibrarytype * ptr)
{
Verify _v;
return foo(ptr);
}

Anyhow, it's done and I'm happy with it. A bit of macro'ing even removes it
all for release builds.

Thanks again for your help.

"Howard" <al*****@hotmail.com> wrote in message
news:4L*********************@bgtnsc05-news.ops.worldnet.att.net...

"Douglas Peterson" <Te******@nospam.msn.com> wrote in message
news:Pa********************@comcast.com...
Instead of inserting an object inside your functions, how about calling
your functions inside a wrapper function? If your function signatures
are the same (or at least if there are a limited number of them), then
this should work. Something like this:

StackCheckVoid( foovoid() );
StackCheckVoid( barvoid() );
int x = StackCheckInt( fooint() ); // where foo int returns an int

Or, even a template to do something similar?

-Howard

That's a very good solution--far too obvious for an idiot such as I -
doh!

I wish I had thought of it before I started.

They are all callback functions that have the exact same signiture,
though I don't see how that might help. There is no way to forward the
'real' address through a check function. I'll have to create a wrapper
for each and change every reference in the source.


As Richard pointed out, I made a mistake there. There shouldn't be
parentheses on the function parameters in my example. But there shouldn't
be a problem passing a function as a parameter. It's easiest if you make
a typedef (alias) for the function type, then use that new type as the
StackCheck function's parameter type. Look up function pointers in your
favorite book.

-Howard

Jul 23 '05 #12

This discussion thread is closed

Replies have been disabled for this discussion.