Google
 
Webnews.only-4-geeks.com
Interesting places
news.only-4-geeks.com Forum Index » C++Goto page 1, 2  Next

Exceptions as smart pointers

 
Jump to:  
 
Sergey P. Derevyago
PostPosted: Thu Aug 07, 2008 7:05 pm    Post subject: Exceptions as smart pointers
       
Long ago I've posted some messages on this topic, in particular this one:
Message-ID: <410A48AB.95A97D57@iobox.com>
LINK

Now I've finished my "C++ multithreading" tutorial and opened a
discussion in comp.programming.threads:
Message-ID: <4899c3e1$0$90276$14726298@news.sunsite.dk>
LINK

But there exist some points that deserve C++ specific attention. And one
of these points is "exceptions being thrown as smart pointers to actual
exception objects".

In particular, the object is being thrown is always sh_ptr<Exception>:
typedef sh_ptr<Exception> shException;
See LINK for
the details.

There also can be nested exceptions and used like this:

void f(mem_pool& mp, int i)
{
shException exc(mp, 0);
try {
g(mp, i);
return;
}
catch (shException she) { if (she->is<MsgException>()) throw; else
exc=she; }
catch (...) { exc=recatchException(mp, _FLINE_); } // recatch!

throw newException(_FLINE_, "Problems in f()", exc); // use as nested!
}

That is we recatch an exception and use it as a nested. The output can
look like this:
-----------------------------------8<-----------------------------------
Exception #1:
ders::Exception [..\tst_exc.cpp:127], message: Problems in f()
ders::Exception [..\tst_exc.cpp:156], message: Problems in g()
ExampleException [..\tst_exc.cpp:136], message: Hello from g()

Exception #2:
ders::Exception [..\tst_exc.cpp:127], message: Problems in f()
ders::Exception [..\tst_exc.cpp:156], message: Problems in g()
ders::StdExternException [..\tst_exc.cpp:154],
typeName="St12out_of_range", message: vector::_M_range_check

Exception #3:
ders::Exception [..\tst_exc.cpp:127], message: Problems in f()
ders::Exception [..\tst_exc.cpp:156], message: Problems in g()
ders::UnknExternException [..\tst_exc.cpp:154], typeName="unknown",
message: Unknown exception

Exception #4:
ders::UnknExternException [..\tst_exc.cpp:110], typeName="unknown",
message: Unknown exception

Non-empty exit message
-----------------------------------8<-----------------------------------
The sources are available here: LINK
So you can compile mtprog\derslib\tst\tst_exc.cpp yourself and se what's
going on.

Function recatchException() is defined as

shException recatchException(mem_pool& mp, const FileLine& location)
{
try { throw; }
catch (shException she) {
return she;
}
catch (const std::exception& se) {
return newStdExternException(mp, location, se.what(),
typeid(se).name());
}
catch (...) {
return newUnknExternException(mp, location, "Unknown exception");
}
}

And you can browse the documentation to quickly get the remaining
details: LINK
--
With all respect, Sergey. LINK
mailto : ders at skeptik.net

--
[ See LINK for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 

 
Mathias Gaunard
PostPosted: Thu Aug 07, 2008 9:26 pm    Post subject: Re: Exceptions as smart pointers
       
On 7 août, 21:05, "Sergey P. Derevyago" <non-exist...@iobox.com>
wrote:

Quote:
catch (shException she) { if (she->is<MsgException>()) throw; else
exc=she; }

catch(const MsgException e) { throw; }


--
[ See LINK for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 

 
Sergey P. Derevyago
PostPosted: Sat Aug 09, 2008 3:58 pm    Post subject: Re: Exceptions as smart pointers
       
Mathias Gaunard wrote:
Quote:
catch (shException she) { if (she->is<MsgException>()) throw; else
exc=she; }

catch(const MsgException e) { throw; }

Are you sure?

--
With all respect, Sergey. LINK
mailto : ders at skeptik.net

--
[ See LINK for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 

 
Mathias Gaunard
PostPosted: Sun Aug 10, 2008 4:28 pm    Post subject: Re: Exceptions as smart pointers
       
On 9 août, 17:58, "Sergey P. Derevyago" <non-exist...@iobox.com>
wrote:
Quote:
Mathias Gaunard wrote:
catch (shException she) { if (she->is<MsgException>()) throw; else
exc=she; }

catch(const MsgException e) { throw; }

Are you sure?

I thought I had put a & there.
Sorry.


--
[ See LINK for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 

 
Sergey P. Derevyago
PostPosted: Mon Aug 11, 2008 12:30 pm    Post subject: Re: Exceptions as smart pointers
       
Mathias Gaunard wrote:
Quote:
catch (shException she) { if (she->is<MsgException>()) throw; else
exc=she; }
catch(const MsgException e) { throw; }

The object is being thrown is always sh_ptr<Exception>:
typedef sh_ptr<Exception> shException;

There is no bare MsgException. Only a sh_ptr<Exception> which
contains MsgException object so you can't catch(const MsgException e).
--
With all respect, Sergey. LINK
mailto : ders at skeptik.net

--
[ See LINK for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 

 
Mathias Gaunard
PostPosted: Mon Aug 11, 2008 10:58 pm    Post subject: Re: Exceptions as smart pointers
       
On 11 août, 14:30, "Sergey P. Derevyago" <non-exist...@iobox.com>
wrote:
Quote:
Mathias Gaunard wrote:
catch (shException she) { if (she->is<MsgException>()) throw; else
exc=she; }
catch(const MsgException e) { throw; }

The object is being thrown is always sh_ptr<Exception>:
typedef sh_ptr<Exception> shException;

Yes. The problem is that throwing smart pointers is stupid.
Throw objects so that you can use the type identification mechanism of
catch-blocks. It's really ridiculous to catch some type and re-
identify it with if-else thingies.

The good way to use exceptions is to throw by value and catch by const-
reference.
That was already established decades ago.


--
[ See LINK for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 

 
Sergey P. Derevyago
PostPosted: Wed Aug 13, 2008 6:58 pm    Post subject: Re: Exceptions as smart pointers
       
Peter Dimov wrote:
Quote:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2509.html

Yes, std::nested_exception could really help.


Quote:
I, personally, would have preferred the N2509 functionality to go
directly into std::exception, but this would have raised ABI
compatibility issues.

But my code works right now. It was published in 2004, to be exact.


Also there is some problem with certain compilers (can be checked with
mtprog\derslib\tst\tst_exc.cpp). The point is that a correct compiler
needs only one catch(...) block:

void f(mem_pool& mp, /* ... */)
{
try {
g(mp, i);
// ...

return;
}
catch (...) {
throw newException(_FLINE_, "Problems in f()",
recatchException(mp, _FLINE_));
}
}

But other compilers crash with this code and require one more catch:

void f(mem_pool& mp, /* ... */)
{
shException exc(mp, 0);
try {
g(mp, i);
// ...

return;
}
catch (shException she) { exc=she; }
catch (...) { exc=recatchException(mp, _FLINE_); }

throw newException(_FLINE_, "Problems in f()", exc);
}

P.S.
The code: LINK
The doxygen: LINK
--
With all respect, Sergey. LINK
mailto : ders at skeptik.net

--
[ See LINK for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 

 
David Abrahams
PostPosted: Mon Aug 25, 2008 3:02 am    Post subject: Re: Exceptions as smart pointers
       
on Thu Aug 07 2008, "Sergey P. Derevyago" <non-existent-AT-iobox.com> wrote:

Quote:
Long ago I've posted some messages on this topic, in particular this one:
Message-ID: <410A48AB.95A97D57@iobox.com
LINK

I've never understood how your solution addresses the problem.

In the above posting, you write:

Quote:
The solution is destructor with in_stack_unwinding parameter:

class A {
// ...
~A(bool in_stack_unwinding) {
if (in_stack_unwinding) { /* ... */ }
else { /* ... */ }
}
};


That appears to only change the interface, but not address the semantic
issues with uncaught_exception. More specifically:

under what conditions will in_stack_unwinding be true above?

If that bool has the same semantics as uncaught_exception(), then all
the problems described in LINK still apply
(let's ignore the "morality" argument given there; I object to the whole
approach).

If you're suggesting semantics equivalent to "is it safe to throw," I
don't _think_ that's actually implementable.

Quote:
But there exist some points that deserve C++ specific attention. And one
of these points is "exceptions being thrown as smart pointers to actual
exception objects".

In particular, the object is being thrown is always sh_ptr<Exception>:
typedef sh_ptr<Exception> shException;
See LINK for
the details.

Can you give a summary of what you achieve by throwing smart pointers?

Quote:
There also can be nested exceptions and used like this:

void f(mem_pool& mp, int i)
{
shException exc(mp, 0);
try {
g(mp, i);
return;
}
catch (shException she) { if (she->is<MsgException>()) throw; else
exc=she; }
catch (...) { exc=recatchException(mp, _FLINE_); } // recatch!

throw newException(_FLINE_, "Problems in f()", exc); // use as nested!
}

And you can browse the documentation to quickly get the remaining
details: LINK

I'm sorry, but that simply seems to link to an HTML-ized copy of the
code, and I don't have the time to try to analyze your code to figure
out what you're trying to accomplish. Summarizing the problem you're
trying to solve, and how your code solves the problem, would help lots.

--
Dave Abrahams
BoostPro Computing
LINK

[ See LINK for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 

 
Sergey P. Derevyago
PostPosted: Mon Aug 25, 2008 1:58 pm    Post subject: Re: Exceptions as smart pointers
       
David Abrahams wrote:
Quote:
class A {
// ...
~A(bool in_stack_unwinding) {
if (in_stack_unwinding) { /* ... */ }
else { /* ... */ }
}
};


That appears to only change the interface, but not address the semantic
issues with uncaught_exception. More specifically:

under what conditions will in_stack_unwinding be true above?

Please refer to 15.2p3: The process of calling destructors for

automatic objects constructed on the path from a try block to a
throw-expression is called "stack unwinding."
I.e. in_stack_unwinding destructor argument is true if the
destructor
was called during the stack unwinding. According to 15.2 if
(in_stack_unwinding) then an exception can leave the destructor without
a terminate().

Quote:
If you're suggesting semantics equivalent to "is it safe to throw," I
don't _think_ that's actually implementable.

But it IS.

The EH-support runtime calls a destructor with
in_stack_unwinding==true
argument so this destructor does really know whether it's safe to throw
exceptions.

Quote:
Can you give a summary of what you achieve by throwing smart pointers?

1. Smart pointers are cheap to copy and the throwing/catching

exceptions supposes copying. So you can create arbitrary big Exception
objects, throw them as sh_ptr<Exception>(/* ... */) and they will be
copied almost for free.
2. sh_ptr copy constructor doesn't throw exceptions so there is no
chance to get terminate() during the copying of sh_ptr<Exception>(). On
the contrary, Exception copy constructor does really throw exceptions so
its copying is expensive and can lead to terminate().
3. It's really easy to create the chains of the nested Exception
objects.
4. Having recatchException() function you can use the following
uniform
exception handler in almost all of the places:

void f()
{
try {
// ...
g();
// ...

return;
}
catch (...) {
throw newException(_FLINE_, "Problems in f()",
recatchException(mp, _FLINE_));
}
}
--
With all respect, Sergey. LINK
mailto : ders at skeptik.net

--
[ See LINK for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 

 
David Abrahams
PostPosted: Tue Aug 26, 2008 3:22 am    Post subject: Re: Exceptions as smart pointers
       
on Mon Aug 25 2008, "Sergey P. Derevyago" <non-existent-AT-iobox.com> wrote:

Quote:
David Abrahams wrote:
class A {
// ...
~A(bool in_stack_unwinding) {
if (in_stack_unwinding) { /* ... */ }
else { /* ... */ }
}
};


That appears to only change the interface, but not address the semantic
issues with uncaught_exception. More specifically:

under what conditions will in_stack_unwinding be true above?

Please refer to 15.2p3: The process of calling destructors for
automatic objects constructed on the path from a try block to a
throw-expression is called "stack unwinding."
I.e. in_stack_unwinding destructor argument is true if the
destructor was called during the stack unwinding. According to 15.2 if
(in_stack_unwinding) then an exception can leave the destructor
without a terminate().

Then that's still not very useful, because the dtor might be called from
inside a catch block where the programmer needs non-throwing operations,
and in_stack_unwinding would be false. A catch block where there is a
final "throw;" is often written as though it were the semantic
equivalent of a dtor; the only difference of course is what happens when
you get another exception, and most programs simply outlaw that
possibility.

Quote:
If you're suggesting semantics equivalent to "is it safe to throw," I
don't _think_ that's actually implementable.

But it IS.

I don't see how. The information about what is "safe" is not encoded in
the program text; it's a function of the semantics the programmer is
trying to achieve.

Basically, it's like this: if you define "safe" to be something that can
be known by the compiler, I claim it's not a useful definition, and if
you define "safe" in a useful way, I claim it's not implementable :-)

Quote:
The EH-support runtime calls a destructor with
in_stack_unwinding==true argument so this destructor does really know
whether it's safe to throw exceptions.

Time to give your definition of "safe," then ;-)

Quote:
Can you give a summary of what you achieve by throwing smart pointers?

1. Smart pointers are cheap to copy and the throwing/catching
exceptions supposes copying.

Throwing requires an accessible copy ctor, but I know of at least one
implementation where you can throw an rvalue without copying it. I
don't see how catching supposes copying. But anyway...

Quote:
So you can create arbitrary big Exception
objects, throw them as sh_ptr<Exception>(/* ... */) and they will be
copied almost for free.

Okay. I *think* the cost of copying exceptions should not be a major
concern. Have you profiled?

Quote:
2. sh_ptr copy constructor doesn't throw exceptions so there
is no chance to get terminate() during the copying of
sh_ptr<Exception>().

Yes, that's a useful known technique.

Quote:
On the contrary, Exception copy constructor does
really throw exceptions so its copying is expensive and can lead to
terminate().

Depends on what Exception is, neh?

Quote:
3. It's really easy to create the chains of the nested Exception
objects.

Okay.

Quote:
4. Having recatchException() function you can use the following
uniform exception handler in almost all of the places:

void f()
{
try {
// ...
g();
// ...

return;
}
catch (...) {
throw newException(_FLINE_, "Problems in f()",
recatchException(mp, _FLINE_));
}

I still don't understand what recatchException is supposed to do.
What's mp above?

--
Dave Abrahams
BoostPro Computing
LINK

[ See LINK for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 

Page 1 of 2 .:. Goto page 1, 2  Next

Google
 
Webnews.only-4-geeks.com

Windows Update | C++ | C | PHP | JavaScript | Photoshop | Programming | Windows 2000 | Python | Windows XP | Object | Flash | Flash - ActionScript | Paint Shop Pro | Excel | PowerPoint | Access | Word | Windows 98 | Internet Explorer 6.0 | CorelDraw12 | Java | XML | asm x86 | Linux Mandrake | Linux RedHat | Outlook |  | news from newsgroups |_ | s

Web Templates

Awesome Website Templates ©

jetbull sklep tuningowy ochrona poznań compensation Yahoo