473,796 Members | 2,690 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

8 years of C++ Exception Handling

Meanwhile there are at least 8 years that compilers exist,
which provide a working implementation of C++ Exception Handling.
Has anything changed meanwhile?
From my point of view nothing has changed
-- people are still using a coding style, which I call
pre-C++-Exception-Handling.
Is this different in your experience?
What is your experience regarding this subject?
I think that a C++ IOstream lib, which is by standard free of exceptions
certainly did not help here.
Jul 22 '05
28 2261

"lilburne" <li******@godzi lla.com> wrote in message
news:bu******** ****@ID-179504.news.uni-berlin.de...
So what do you consider post-C++-Exception-Handling?

Being aware of that certain statements may throw and writing code, which
does not ignore this fact.
Writing code that relies on the fact that it will only be executed if and
only if all previous statements have executed successfully.
Matching design philosophies including e.g.
* the notion of non-corrupting fail of an operation
* the notion that the enduser can expect to see a descriptive error
message,
which includes any system error message and maybe even stack-trace
information, e.g.:
Cannot parse input file "test.cpp", because of
Cannot start preprocessor, because of
maximum number of processes reached
I don't tolerate exceptions other than from data input from files or
other external data sources. Once data has been accepted, there should
be no exceptional conditions, and data created internally should not
cause an exceptional condition.

so you ignore that new may throw?
so you ignore that opening a file for writing may fail?
After that everything else failing is a bug/algorithm failure, and
outside the scope of legitimate handling by exceptions.

assertions are still useful
Jul 22 '05 #21
Frank Puck wrote:
"lilburne" <li******@godzi lla.com> wrote in message
news:bu******** ****@ID-179504.news.uni-berlin.de...

So what do you consider post-C++-Exception-Handling?
Being aware of that certain statements may throw and writing code, which
does not ignore this fact.


I'd much rather not have any throws thanks you very much.
Writing code that relies on the fact that it will only be executed if and
only if all previous statements have executed successfully.
They damn well ought to have or the CPU needs replacing.
Matching design philosophies including e.g.
* the notion of non-corrupting fail of an operation

An operation unless it is permissible for the operation to
fail it is a coding/design bug.

* the notion that the enduser can expect to see a descriptive error
message,
which includes any system error message and maybe even stack-trace
information, e.g.:
Cannot parse input file "test.cpp", because of
Cannot start preprocessor, because of
maximum number of processes reached

Exceptions aren't a prerequisite for informative system
error messages.

What is the user going to do with a stack trace?

I don't tolerate exceptions other than from data input from files or
other external data sources. Once data has been accepted, there should
be no exceptional conditions, and data created internally should not
cause an exceptional condition.
so you ignore that new may throw?

Pretty much. If a calculation's memory requirements exceeds
the virtual address space, all the messing about in the
world ain't going obtain more. Now in our new handler we'll
release a few Mb which we reserved for such eventualities
and we'll set a flag to abort the current calculation, but
of course at this point no exception has fired.

so you ignore that opening a file for writing may fail?


We don't have any file IO that thows. At least not as far as
application code is concerned. If there is any throwing by
any particular OS it don't propagate outside of the wrapper
classes.

After that everything else failing is a bug/algorithm failure, and
outside the scope of legitimate handling by exceptions.


assertions are still useful


Indeed they are.

Jul 22 '05 #22
lilburne wrote:

You'd probably hate mine too. Minimal runtime checking but heavily laced
with assertions. Violate a precondition and in a debug run - kerboom.


This is probably the fundamental disagreement between our approaches.

Consider this:

{

BaseClass* base = someFunction... .
DerivedClass* derived = std::dynamic_ca st<DerivedClass >(base);

// I assume you use something like this for a 'debug' release
#ifdef DEBUG
assert(derived) ;
#endif // DEBUG

}

This code definitely helps developers make sure that after the cast,
derived is not NULL. Therefore developers are forced to add runtime
checking code. With properly designed exception code, you will not
execute code after an 'invalid' state, therefore simplifying code
construction.

For example if operation_<n> functions throw exceptions, the following
code will break if obj is in an 'invalid' state anywhere in the process.

Object obj;
operation_1_thr ows(obj);
operation_2_thr ows(obj);
operation_3_thr ows(obj);
operation_4_thr ows(obj);

This is much more readable an simple to encapsulate in try/catch than
the following code.

Object obj;

if(STATUS_OK != operation_1_ret (obj))
{
// failed here, handle this in some way
}
else if(STATUS_OK != operation_2_ret (obj))
{
// failed at operation_2, handle here
}
else if(STATUS_OK != operation_3_ret (obj))
{
// failed at operation_3, handle here
}
else if(STATUS_OK != operation_4_ret (obj))
{
// failed at operation_4, handle here
}

I do understand that there is a place for this type of code, all I'm
saying is that exceptions can be very useful and are, in some instances
(I'm pretty sure this topic has been brought to death in this or some
other forum...), better design solutions than return codes and even you
beloved assertions.

Cheers,

Jorge
Jul 22 '05 #23
"Jorge Rivera" <jo*****@roches ter.rr.com> wrote in message
news:Z4******** ***********@twi ster.nyroc.rr.c om...
lilburne wrote:
Consider this:

{

BaseClass* base = someFunction... .
DerivedClass* derived = std::dynamic_ca st<DerivedClass >(base);

// I assume you use something like this for a 'debug' release
#ifdef DEBUG
assert(derived) ;
#endif // DEBUG

}


If you're willing to assume in release mode that base can be
static_cast'd to DerivedClass, then you should use static_cast. The
dynamic_cast, together with the assertion, can be used in debug mode.

Jonathan
Jul 22 '05 #24
Jonathan Turkanis wrote:
"Jorge Rivera" <jo*****@roches ter.rr.com> wrote in message
news:Z4******** ***********@twi ster.nyroc.rr.c om...
lilburne wrote:
Consider this:

{

BaseClass* base = someFunction... .
DerivedClas s* derived = std::dynamic_ca st<DerivedClass >(base);

// I assume you use something like this for a 'debug' release
#ifdef DEBUG
assert(derived) ;
#endif // DEBUG

}

If you're willing to assume in release mode that base can be
static_cast'd to DerivedClass, then you should use static_cast. The
dynamic_cast, together with the assertion, can be used in debug mode.


I guess you are an MSVC++ developer only, right? There is no definition
in C++ about 'debug' or 'release' versions. Whatever optimizations
Microsoft uses does not change what standard behavior is. The use of
dynamic_cast over static_cast is a design decision, nor a build decision.

I do appreciate the comment, as I did not know this about MSVC++ (if you
use a different compiler, let me know).

Jorge L.

Jonathan

Jul 22 '05 #25
On Sat, 24 Jan 2004 21:44:57 GMT, Jorge Rivera
<jo*****@roches ter.rr.com> wrote:
lilburne wrote:


Jorge Rivera wrote:
lilburne wrote:
After that everything else failing is a bug/algorithm failure, and
outside the scope of legitimate handling by exceptions.

What is an error? Other than user input problems, hardware failure, etc
I wouldn't accept that there are any errors that aren't bugs.


That's your definition of an error, and I guess I have the freedom of
designing my classes to define error as something different, right?

In your example how do *you* know that failure 'if(ret == -1)' wasn't what
I was coding for? By throwing an exception *you* have dictated that *my*
code
does its processing inside a catch block, which just seems plain odd.


But that's exactly what I want. I do not allow you to continue without
checking for the error. You CAN NOT ignore it, even if it causes you
the paing of processing the error in a catch block, it is better (and
ths is, of course, just my perspective and programming approach) than
just allowing you to ignore the return code.


You can create return values that have to be checked.

template <class T>
struct ret_value
{
ret_value(T const& value)
:m_value(value) , m_checked(false ) {}

~ret_value()
{
if (!m_checked)
std::terminate( );
}

T& get()
{
m_checked = true;
return m_value;
}

operator T&()
{
return get();
}

private:
T m_value;
bool m_checked;
};

or similar. Exceptions aren't there to force you to handle errors,
they're there to allow you to handle an errors at the point that you
have enough information available to handle the error without manually
returning it up the call stack.

Tom

C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Jul 22 '05 #26
tom_usenet wrote:
On Sat, 24 Jan 2004 21:44:57 GMT, Jorge Rivera
<jo*****@roches ter.rr.com> wrote:

lilburne wrote:


Jorge Rivera wrote:
lilburne wrote:
>After that everything else failing is a bug/algorithm failure, and
>outside the scope of legitimate handling by exceptions.
>
What is an error? Other than user input problems, hardware failure, etc
I wouldn't accept that there are any errors that aren't bugs.


That's your definition of an error, and I guess I have the freedom of
designing my classes to define error as something different, right?

In your example how do *you* know that failure 'if(ret == -1)' wasn't what
I was coding for? By throwing an exception *you* have dictated that *my*
code
does its processing inside a catch block, which just seems plain odd.


But that's exactly what I want. I do not allow you to continue without
checking for the error. You CAN NOT ignore it, even if it causes you
the paing of processing the error in a catch block, it is better (and
ths is, of course, just my perspective and programming approach) than
just allowing you to ignore the return code.

You can create return values that have to be checked.

template <class T>
struct ret_value
{
ret_value(T const& value)
:m_value(value) , m_checked(false ) {}

~ret_value()
{
if (!m_checked)
std::terminate( );
}

T& get()
{
m_checked = true;
return m_value;
}

operator T&()
{
return get();
}

private:
T m_value;
bool m_checked;
};

or similar. Exceptions aren't there to force you to handle errors,
they're there to allow you to handle an errors at the point that you
have enough information available to handle the error without manually
returning it up the call stack.


Even if this was the original intention of exceptions, that is the way I
like using them. Although the approach you present serves the purpose
of making sure that clients check status variables, there are design
disadvantages to this approach (OK, that was a stupid comment, as that
applies to everything in this discussion....) .

I hadn't thought of this approach though, and it appears very useful.
In the future I may do more things like this to reduce dependency on
exception handling mechanisms. Thanks,

Jorge L.
Tom

C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html

Jul 22 '05 #27


Jorge Rivera wrote:
lilburne wrote:

You'd probably hate mine too. Minimal runtime checking but heavily
laced with assertions. Violate a precondition and in a debug run -
kerboom.
This is probably the fundamental disagreement between our approaches.

Consider this:

{

BaseClass* base = someFunction... .
DerivedClass* derived = std::dynamic_ca st<DerivedClass >(base);

// I assume you use something like this for a 'debug' release
#ifdef DEBUG
assert(derived) ;
#endif // DEBUG

}

This code definitely helps developers make sure that after the cast,
derived is not NULL. Therefore developers are forced to add runtime
checking code. With properly designed exception code, you will not
execute code after an 'invalid' state, therefore simplifying code
construction.

Yes this is the fundamental difference.

We would say that if someFunction is returning BaseClass* then the
calling code should handle a BaseClass. Dynamic casting might help to
select efficient methods for processing different types of DerivedClass,
but it is a bug not to handle the general case too.

Alternatively it might be a post-condition that someFunction always
returns DerivedClass, if someFunction subsequently changes so that it
returns other things that is an API change and I don't think that
calling code should be testing for API changes in the code it calls.
Where would it end?

If the assumption is that someFunction always returns a DerivedClass
then the assert is sufficient (BTW no conditional required).

The technical problem we have with exceptions is the overhead of stack
unwinding. A simple test I wrote a month or so ago had gcc 3.3 5 times
slower in the presence of a try, throw, catch than an assert. This seems
to be a particular problem with 3.3 as our previous tests have only
shown a 20% performance degradation. Performance is a critical factor to
our customers as calculations can take several hours and even days in
some cases, and whilst we tend to be the fastest in the industry taking
a hit for something that should never occur seems to be too much to ask.
I'd rather that 20% was spent on improving surface quality then trapping
bugs at runtime.

A phillosophical problem we have is that it assumes that the calling
code is going to catch the exception. But if the caller couldn't be
bothered to ensure that the arguments being passed were such that the
called code could proceed then it is unlikely the caller will bother to
catch an exception either. Probably somewhere up in the main loop there
is a catch(...) but this seems like an aweful cop-out.

For example if operation_<n> functions throw exceptions, the following
code will break if obj is in an 'invalid' state anywhere in the process.

Object obj;
operation_1_thr ows(obj);
operation_2_thr ows(obj);
operation_3_thr ows(obj);
operation_4_thr ows(obj);
Well again we'd say that a precondition of each of these functions is
that 'obj' is not invalid.

void operation_1(Obj ect &obj) {
assert(obj.inva lid() == false);
// perform operation1
}
perhaps our applications are such that we have full control over the
objects we create, outside of I/O our objects don't become invalid.

We certainly wouldn't expect that a consequence of calling operation_1
would be to cause a perfectly good 'obj' to become invalid. Perhaps
operation_1 initializes 'obj'? In which case we wouldn't expect
operation_2 to cause a perfectly good 'obj' to be come invalid.

I don't see the additional clarity of:

try {
Object obj;
operation_1_thr ows(obj);
operation_2_thr ows(obj);
operation_3_thr ows(obj);
operation_4_thr ows(obj);
}
catch (...) {
}

over

Object obj;
if (MY_OK == operation_1(obj ))
operation_2(obj );
operation_3(obj );
operation_4(obj );
} else {
}


(I'm pretty sure this topic has been brought to death in this or some
other forum...), better design solutions than return codes and even you
beloved assertions.


Better design solutions are always preferable.

Jul 22 '05 #28
lilburne wrote:
The technical problem we have with exceptions is the overhead of stack
unwinding. A simple test I wrote a month or so ago had gcc 3.3 5 times
slower in the presence of a try, throw, catch than an assert. This seems
to be a particular problem with 3.3 as our previous tests have only
shown a 20% performance degradation. Performance is a critical factor to
our customers as calculations can take several hours and even days in
some cases, and whilst we tend to be the fastest in the industry taking
a hit for something that should never occur seems to be too much to ask.
I'd rather that 20% was spent on improving surface quality then trapping
bugs at runtime.


I understand your point and your design considerations. I agree that
exceptions should not be used everywhere just because, and that
exception handling is expensive. Sounds like your design is perfectly
valid.

Some of my systems are much more unreliable (not my code, the system it
acts upon), and external factors come into play much more often than
not. In these cases, the use of exceptions becomes somewhat more
important.

I am not sure exception handling is much more expensive if you are
already using RTTI, which some of my clients already use, though.

Thanks,

Jorge L.

Jul 22 '05 #29

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

Similar topics

11
2888
by: adi | last post by:
Dear all, This is more like a theoretical or conceptual question: which is better, using exception or return code for a .NET component? I had created a COM object (using VB6), which uses return code (not generating error/exception) so it is more compatible with other programming language.
7
6007
by: Noor | last post by:
please tell the technique of centralize exception handling without try catch blocks in c#.
3
2752
by: Master of C++ | last post by:
Hi, I am an absolute newbie to Exception Handling, and I am trying to retrofit exception handling to a LOT of C++ code that I've written earlier. I am just looking for a bare-bones, low-tech exception handling mechanism which will allow me to pass character information about an error and its location from lower-level classes. Can you please critique the following exception handling mechanism in terms of my requirements ?
2
2596
by: tom | last post by:
Hi, I am developing a WinForm application and I am looking for a guide on where to place Exception Handling. My application is designed into three tiers UI, Business Objects, and Data Access Layer. My questions is where should I put exception handling: 1) Should it be put in all significant methods in all layers? 2) Should I create an exception base class that will handle the errors and pass useful error messages to the user?
9
2538
by: C# Learner | last post by:
Some time ago, I remember reading a discussion about the strengths and weaknesses of exception handling. One of the weaknesses that was put forward was that exception handling is inefficient (in the way of CPU usage), compared to the "normal" practise returning values. How true is this? Will using using exception handling, in general, be much less efficient than returning values, or less efficient at all? Just curious...
44
4231
by: craig | last post by:
I am wondering if there are some best practices for determining a strategy for using try/catch blocks within an application. My current thoughts are: 1. The code the initiates any high-level user tasks should always be included in a try/catch block that actually handles any exceptions that occur (log the exception, display a message box, etc.). 2. Low-level operations that are used to carry out the high level tasks
4
5136
by: Ele | last post by:
When Exception handling disabled compiler still spits out "C++ exception handler used." Why is that? Why does it ask for "Specify /EHsc"? Thanks! c:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\xstring(1453) : warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc
41
3081
by: Zytan | last post by:
Ok something simple like int.Parse(string) can throw these exceptions: ArgumentNullException, FormatException, OverflowException I don't want my program to just crash on an exception, so I must handle all of them. I don't care about which one happened, except to write out exception.Message to a log file. It seems verbose to write out three handlers that all do the same thing. So, I could just catch Exception. But, is that...
1
3110
by: George2 | last post by:
Hello everyone, Such code segment is used to check whether function call or exception- handling mechanism runs out of memory first (written by Bjarne), void perverted() { try{
0
9679
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
1
10172
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
10003
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
9050
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
7546
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
6785
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();...
1
4115
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
2
3730
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2924
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.