Deleting exceptions after throwing

E

Emil Berg

Hello,

After reading some articles about exceptions, I still have an
unanswered question.

If I throw an exception as an object on the heap with this way:
throw new FileNotFoundException();

Then, is it possible to catch the exception as a reference and delete
the allocated exception object somehow from the throwing site?

Thanks,
Emil.
 
R

Ron

Hello,

After reading some articles about exceptions, I still have an
unanswered question.

If I throw an exception as an object on the heap with this way:
throw new FileNotFoundException();

Then, is it possible to catch the exception as a reference and delete
the allocated exception object somehow from the throwing site?
You're throwing a pointer. You catch the pointer and delete it.
However, why are you throwing a pointer? Why not just throw
the object itself:
throw FileNotFoundException();

Your exception objects should be relatively easy to copy by design.

Never use dynamic allocation without an overriding reason. You can
catch the objects by reference if you're trying to handle things
polymorphicly.
 
E

Emil Berg

You're throwing a pointer.   You catch the pointer and delete it.
However, why are you throwing a pointer?   Why not just throw
the object itself:
    throw FileNotFoundException();

Your exception objects should be relatively easy to copy by design.

Never use dynamic allocation without an overriding reason.   You can
catch the objects by reference if you're trying to handle things
polymorphicly.

What I want to do is pass exceptions between threads. I have some
exception classes that derive from CBaseException class.
Now I'm doing the following steps:
1. Throw FileNotFoundException on thread A
2. Catch it as CBaseException and save it in an CBaseException*
pointer.
3. Pass this pointer to thread B
4. Throw this exception manually.
5. Catching the exception on thread B as FileNotFoundException
reference

Steps 2,3,4 are part of a threading/messaging infrastructure that I'm
building, so I'd like to delete the exception on thread B after
throwing it (inside the infrastructure).
I don't want the user to delete the exception.

I hope that I explained it well and maybe you have a good idea to
solve it.

Thanks for helping!
Emil.
 
A

Alan Woodland

Emil Berg wrote:
[snip]
What I want to do is pass exceptions between threads. I have some
exception classes that derive from CBaseException class.
Now I'm doing the following steps:
1. Throw FileNotFoundException on thread A
2. Catch it as CBaseException and save it in an CBaseException*
pointer.
3. Pass this pointer to thread B
4. Throw this exception manually.
5. Catching the exception on thread B as FileNotFoundException
reference

Steps 2,3,4 are part of a threading/messaging infrastructure that I'm
building, so I'd like to delete the exception on thread B after
throwing it (inside the infrastructure).
I don't want the user to delete the exception.

I hope that I explained it well and maybe you have a good idea to
solve it.
Why not use something like auto_ptr around step 4 so that when you hit
the throw it gets deleted during stack unwinding?

Alan
 
E

Emil Berg

C++0x has a mechanism for this. Inside a catch clause, you call
std::current_exception(), which gives you back an opaque pointer of type
std::exception_ptr to the current exception object. The exception object
stays around as long as there's an exception_ptr object pointing to it.
You can also rethrow the original exception, and the exception_ptr
object remains valid.

--
   Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of
"The Standard C++ Library Extensions: a Tutorial and Reference"
(www.petebecker.com/tr1book)

Now I've read about this concept.
It looks good, but I tried to use exception_ptr in a regular win32
application in visual studio 2008, and the compiler cannot find this
class.
Also, I'm not sure that I can use exception_ptr, because I want my
code also to work on Window Mobile, and I don't know if stdexcept.h
exists there.

Anybody has an idea?
 
E

Emil Berg

Emil Berg wrote:

[snip]
What I want to do is pass exceptions between threads. I have some
exception classes that derive from CBaseException class.
Now I'm doing the following steps:
1. Throw FileNotFoundException on thread A
2. Catch it as CBaseException and save it in an CBaseException*
pointer.
3. Pass this pointer to thread B
4. Throw this exception manually.
5. Catching the exception on thread B as FileNotFoundException
reference
Steps 2,3,4 are part of a threading/messaging infrastructure that I'm
building, so I'd like to delete the exception on thread B after
throwing it (inside the infrastructure).
I don't want the user to delete the exception.
I hope that I explained it well and maybe you have a good idea to
solve it.

Why not use something like auto_ptr around step 4 so that when you hit
the throw it gets deleted during stack unwinding?

Alan

If I throw auto_ptr<FileNotFoundException> then the user needs to
catch auto_ptr<FileNotFoundException>.
I want the user to catch just FileNotFoundException and not its
auto_ptr.
 
P

Pascal J. Bourguignon

Emil Berg said:
Emil Berg wrote:

[snip]
What I want to do is pass exceptions between threads. I have some
exception classes that derive from CBaseException class.
Now I'm doing the following steps:
1. Throw FileNotFoundException on thread A
2. Catch it as CBaseException and save it in an CBaseException*
pointer.
3. Pass this pointer to thread B
4. Throw this exception manually.
5. Catching the exception on thread B as FileNotFoundException
reference
Steps 2,3,4 are part of a threading/messaging infrastructure that I'm
building, so I'd like to delete the exception on thread B after
throwing it (inside the infrastructure).
I don't want the user to delete the exception.
I hope that I explained it well and maybe you have a good idea to
solve it.

Why not use something like auto_ptr around step 4 so that when you hit
the throw it gets deleted during stack unwinding?

Alan

If I throw auto_ptr<FileNotFoundException> then the user needs to
catch auto_ptr<FileNotFoundException>.
I want the user to catch just FileNotFoundException and not its
auto_ptr.

class TheActualFileNotFoundException:public std::exception {
....
};
typedef auto_ptr<TheActualFileNotFoundException> FileNotFoundException;
 
E

Emil Berg

Emil Berg said:
Emil Berg wrote:
[snip]
What I want to do is pass exceptions between threads. I have some
exception classes that derive from CBaseException class.
Now I'm doing the following steps:
1. Throw FileNotFoundException on thread A
2. Catch it as CBaseException and save it in an CBaseException*
pointer.
3. Pass this pointer to thread B
4. Throw this exception manually.
5. Catching the exception on thread B as FileNotFoundException
reference
Steps 2,3,4 are part of a threading/messaging infrastructure that I'm
building, so I'd like to delete the exception on thread B after
throwing it (inside the infrastructure).
I don't want the user to delete the exception.
I hope that I explained it well and maybe you have a good idea to
solve it.
Why not use something like auto_ptr around step 4 so that when you hit
the throw it gets deleted during stack unwinding?
Alan
If I throw auto_ptr<FileNotFoundException> then the user needs to
catch auto_ptr<FileNotFoundException>.
I want the user to catch just FileNotFoundException and not its
auto_ptr.

class TheActualFileNotFoundException:public std::exception {
...};

typedef auto_ptr<TheActualFileNotFoundException> FileNotFoundException;

So the user needs to catch FileNotFoundException and call get()
function to get the actual exception.
It's more complicated for the user from just deleting it :)
 
P

Pascal J. Bourguignon

Emil Berg said:
So the user needs to catch FileNotFoundException and call get()
function to get the actual exception.
It's more complicated for the user from just deleting it :)

Not at all. Auto_ptr implements operator-> so you can use them just
as you would with normal objects.

....
catch(FileNotFoundException& e){
std::cout<<"Cannot find file "<<e->getPathname()<<" because "<<e->getErrorMessage()<<std::endl;
}
 
E

Emil Berg

Not at all.  Auto_ptr implements operator-> so you can use them just
as you would with normal objects.

...
catch(FileNotFoundException& e){
  std::cout<<"Cannot find file "<<e->getPathname()<<" because "<<e->getErrorMessage()<<std::endl;

}

Oh, I didn't know. Then it's a very good idea.
But there is still another problem.
When the user is throwing the exception, he will need to throw
TheActualFileNotFoundException, becuase FileNotFoundException is a
typedef to the smart pointer.
 
G

Gert-Jan de Vos

What I want to do is pass exceptions between threads. I have some
exception classes that derive from CBaseException class.

See here for an elegant solution that works in C++98:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2106.html

Basically in your CBaseException class, define virtual clone() and
throw() functions.

No your thread library can clone() exception objects across thread
boundaries and
re-throw the exception in the new thread. The nice thing is that user
code doesn't
see the difference except that all your exception objects must
implement both
support functions. You can make a simple template to help with that.
 
E

Emil Berg

See here for an elegant solution that works in C++98:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2106.html

Basically in your CBaseException class, define virtual clone() and
throw() functions.

No your thread library can clone() exception objects across thread
boundaries and
re-throw the exception in the new thread. The nice thing is that user
code doesn't
see the difference except that all your exception objects must
implement both
support functions. You can make a simple template to help with that.

This post is exactly what I'm doing :)
But still there is a memory leak in their example, because when
exception is cloned and then thrown, it is caught with reference type
and not deleted.
 
G

Gert-Jan de Vos

This post is exactly what I'm doing :)
But still there is a memory leak in their example, because when
exception is cloned and then thrown, it is caught with reference type
and not deleted.

You don't throw the cloned object directly. I suggest to wrap the
cloned
exception object from clone() in an auto_ptr:

auto_ptr<cloneable_exception> clone();

This returns new ConcreteException(*this) for all your
ConcreteException::clone() implementations.

Now the ownership of the new-ed ConcreteException object is with your
thread library. In the destination thread, your thread library calls
dynamic_throw() on the cloned exception object.

Now each ConcreteException in turn implements this:

void ConcreteException::dynamic_throw() { throw *this; }

Such that your cloned exception gets re-thrown by value again. The
auto_ptr that owned the cloned exception will clean up after the throw
resulting from dynamic_throw().

You can easily support this in your thread library by
having a catch (cloneable_exception&) handler in your library's thread
start function.

You see that the new-ed clone and pointers can be hidden in your
thread
library while the user just sees idiomatic exception objects by value.
There is one extra copy (clone) to transport the exception object over
the thread boundary and one possible extra copy for storing the
exception
object while the second thread's call stack unwinds.
 
E

Emil Berg

You don't throw the cloned object directly. I suggest to wrap the
cloned
exception object from clone() in an auto_ptr:

auto_ptr<cloneable_exception> clone();

This returns new ConcreteException(*this) for all your
ConcreteException::clone() implementations.

Now the ownership of the new-ed ConcreteException object is with your
thread library. In the destination thread, your thread library calls
dynamic_throw() on the cloned exception object.

Now each ConcreteException in turn implements this:

void ConcreteException::dynamic_throw() { throw *this; }

Such that your cloned exception gets re-thrown by value again. The
auto_ptr that owned the cloned exception will clean up after the throw
resulting from dynamic_throw().

You can easily support this in your thread library by
having a catch (cloneable_exception&) handler in your library's thread
start function.

You see that the new-ed clone and pointers can be hidden in your
thread
library while the user just sees idiomatic exception objects by value.
There is one extra copy (clone) to transport the exception object over
the thread boundary and one possible extra copy for storing the
exception
object while the second thread's call stack unwinds.

Good idea !!!!
Thank you, now it's solved !!!

Also, thanks to everyone else that helped.
 
J

James Kanze

What I want to do is pass exceptions between threads. I have
some exception classes that derive from CBaseException class.
Now I'm doing the following steps:
1. Throw FileNotFoundException on thread A
2. Catch it as CBaseException and save it in an CBaseException*
pointer.
3. Pass this pointer to thread B
4. Throw this exception manually.
5. Catching the exception on thread B as FileNotFoundException
reference
Steps 2,3,4 are part of a threading/messaging infrastructure
that I'm building, so I'd like to delete the exception on
thread B after throwing it (inside the infrastructure). I
don't want the user to delete the exception.
I hope that I explained it well and maybe you have a good idea
to solve it.

I'd still probably use copy's locally (within the thread), and
catch by const reference. Only at the outer layer of the thread
would I clone the exception and pass it to the other thread (by
pointer).

Note that for this to work, the base class of your exceptions
must have two virtual functions, reimplemented in all derived
classes: clone (in order to copy the dynamic type) and raise (in
order to raise the correct type of exception---throw uses the
static type).
 
J

James Kanze

Emil Berg said:
Emil Berg wrote:
[snip]
What I want to do is pass exceptions between threads. I
have some exception classes that derive from
CBaseException class. Now I'm doing the following steps:
1. Throw FileNotFoundException on thread A
2. Catch it as CBaseException and save it in an CBaseException*
pointer.
3. Pass this pointer to thread B
4. Throw this exception manually.
5. Catching the exception on thread B as FileNotFoundException
reference
Steps 2,3,4 are part of a threading/messaging
infrastructure that I'm building, so I'd like to delete
the exception on thread B after throwing it (inside the
infrastructure). I don't want the user to delete the
exception.
I hope that I explained it well and maybe you have a good
idea to solve it.
Why not use something like auto_ptr around step 4 so that
when you hit the throw it gets deleted during stack
unwinding?
If I throw auto_ptr<FileNotFoundException> then the user
needs to catch auto_ptr<FileNotFoundException>. I want the
user to catch just FileNotFoundException and not its
auto_ptr.
class TheActualFileNotFoundException:public std::exception {
...};
typedef auto_ptr<TheActualFileNotFoundException> FileNotFoundException;

That doesn't work for inheritance hierarchies. In other words,
if you throw auto_ptr< TheActualFileNotFoundException >, it
won't be caught by:
catch ( auto_ptr< TheActualExceptionBaseType > const& )
Which sort of defeats the purpose of subclassing.
 
J

James Kanze

See here for an elegant solution that works in C++98:

Basically in your CBaseException class, define virtual clone()
and throw() functions.

The code doesn't really define a function named throw, does it?
(I'd call it raise. Just a personal preference.)
 
G

Gert-Jan de Vos

The code doesn't really define a function named throw, does it?
(I'd call it raise.  Just a personal preference.)

From n2106:

class cloneable
{
public:
virtual cloneable * dynamic_clone() const =0;
virtual void dynamic_throw() const =0;
virtual ~cloneable() {}
};

Maybe cloneable_exception/clone()/raise() are better names. And
I would have clone() return an auto_ptr<cloneable_exception>.
 
E

Emil Berg

Emil Berg said:
Emil Berg wrote:
[snip]
What I want to do is pass exceptions between threads. I
have some exception classes that derive from
CBaseException class.  Now I'm doing the following steps:
1. Throw FileNotFoundException on thread A
2. Catch it as CBaseException and save it in an CBaseException*
pointer.
3. Pass this pointer to thread B
4. Throw this exception manually.
5. Catching the exception on thread B as FileNotFoundException
reference
Steps 2,3,4 are part of a threading/messaging
infrastructure that I'm building, so I'd like to delete
the exception on thread B after throwing it (inside the
infrastructure).  I don't want the user to delete the
exception.
I hope that I explained it well and maybe you have a good
idea to solve it.
Why not use something like auto_ptr around step 4 so that
when you hit the throw it gets deleted during stack
unwinding?
If I throw auto_ptr<FileNotFoundException> then the user
needs to catch auto_ptr<FileNotFoundException>.  I want the
user to catch just FileNotFoundException and not its
auto_ptr.
class TheActualFileNotFoundException:public std::exception {
...};
typedef auto_ptr<TheActualFileNotFoundException> FileNotFoundException;

That doesn't work for inheritance hierarchies.  In other words,
if you throw auto_ptr< TheActualFileNotFoundException >, it
won't be caught by:
    catch ( auto_ptr< TheActualExceptionBaseType > const& )
Which sort of defeats the purpose of subclassing.

* When I override Clone() in each child class, I write the following
line of code (For instance, in the class of FileNotFound):
return auto_ptr<CloneableException>(new FileNotFoundException(*this));
* When I override Throw() in each child clss, I write the following:
throw *this;

*When catching in the middle I use the following:
catch (const CloneableException& ex)
{
exPassed = ex.Clone();
}

*Then I rethrow it this way:
CloneableException* ex = exPassed.get();
ex->Throw();

*At the end I catch it this way:
catch(const FileNotFoundException& ex)

And it worked for me.
Thanks!
 
G

Gert-Jan de Vos

* When I override Clone() in each child class, I write the following
line of code (For instance, in the class of FileNotFound):
return auto_ptr<CloneableException>(new FileNotFoundException(*this));
* When I override Throw() in each child clss, I write the following:
throw *this;

Or even:

template <typename T>
struct CloneableExceptionImpl : CloneableException
{
virtual std::auto_ptr<CloneableException> Clone()
{
return std::auto_ptr<CloneableException>(new T(*static_cast<T*>
(this)));
}

virtual void Throw()
{
throw *static_cast<T*>(this);
}
};

class FileNotFoundException : public
CloneableExceptionImpl<FileNotFoundException>
{
// ...
};
*Then I rethrow it this way:
CloneableException* ex = exPassed.get();
ex->Throw();

Or even just:

exPassed->Throw();
And it worked for me.
Thanks!

Great!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top