Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Error codes vs. exceptions

Reply
Thread Tools

Error codes vs. exceptions

 
 
Balog Pal
Guest
Posts: n/a
 
      06-04-2012
"mike3" <(E-Mail Removed)>
>> >Is it a good idea to default to exceptions for errors, and then if after
>> >you start actually using the code, it looks like an error code is more
>> >appropriate, to use that instead?

>
>> Yes. As I mentioned for some operations there's a need for both forms.
>> Fortuneately it's not hard to write converters in either direction, and
>> then
>> clients can use the better-suited variant.


>So then you _do_ need a translation layer than translates error codes
>to exceptions and exceptions to error codes, and thus need a 1-to-1
>correspondence between the two, with exception classes for every error
>code in your error code enum


I wonder how you arrived at that conclusion.

The conversion is there tof *practical* purposes, and does exactly what is
considered practical. It may swallow some conditions, turn everrything into
bool, or whatever. A possible approach is to have a single exception class
with just a string, and the converter fetches the error string from the
source (like perror) and emits that.

You'd need the original enums only if planned to act on them, but if you
want that, you don;t use the converter in the first place, but call the
original.

>(it seems that in the examples in the
>C++ "bible" (Stroustrup), they have exception classes for every type of
>exception that can occur. Also, I've heard stuff about not including type
>fields in exceptions, and type fields being a bad idea in general, and it's
>better to use different classes + inheritance instead of type fields.)?


Another practical design question. I already suggested to start with the
code that acts on the error condition, then design all the rest to supply it
the proper info in the most convenient form.

>And thus the need to update several statements in the program when
>adding new errors:


If you replace the library to one woth a different specification (like the
function you called this far changed its return codes, and added some new
ones) you certainly need to update the code. If unused parts of the library
do anything, including undergo extension or changes, it should not change
your existing code in any way.

update the error code list and add a new exception
class and also update the translator.

>So perhaps maybe I should call an exception to the no-type-field rule
>because it's causing gains in complexity and a reduction in
>maintainability?
>Then we only need to add codes to the error code list and don't need to
>mess with anything else. After all, the rule is supposed to help
>maintainability,
>so if you're running into a situation where it's hurting it, better to call
>an
>exception to the rule. Remember that programming is not based on hard
>rules. Or don't bother with two-way translation, and allow for
>separate and distinct sets of error codes and exceptions.


I have an impression that you chase made-up problems instead of dealing with
real ones.

Watch the baton not the runners.

>(Why is a 1-1 correspondence needed? Because consider if the sets
>are different: How do we determine what to translate to? Suppose we have
>error codes for "XPARAMOUTOFRANGE" and "YPARAMOUTOFRANGE"
>but only a single "OutOfRange" exception.


And as you're supposed to pass both params strictly in-range, all of those
are obsolete.

And as a debug aid during development you use assert in the function. If you
really want the excepton a single string-exception with those quotes shall
do.

>We can translate the codes
>to exception, but how can we do the reverse translation? There's an
>ambiguity.)


Why would you want the reverse translation?

.....
>This idea seems to suggest prefer exceptions, and not limit them to a
>minority
>of errors, otherwise in the majority of errors we'll be mixing reaction
>logic with
>action logic (see above).


In so many words.

>So then a translation layer (error codes <-> exceptions) is vital.


No it is not, just is pretty common. Mostly because we use external
components, all following their own style and we translate those to fit our
system if the difference is big.

> So what about the problems mentioned at the beginning of this post?


You made those up ;-> to a fair level.



 
Reply With Quote
 
 
 
 
Pavel
Guest
Posts: n/a
 
      06-04-2012
Balog Pal wrote:
>
> "Pavel" <(E-Mail Removed)>
>
>> 2. C++ functions with exception specifications. A programmer is reminded about
>> possible error conditions if s/he has function prototype in front of him or
>> her while coding the call.

>
> The what? Did you read what those do in C++? Or typical rationalt to (not) use
> them, ie. at Boost with cool explanation? Or at MS that just refused to
> implement this braindead feature? Looking ahead in time, as in C++11 this
> feature became deprecated.

I am sorry, what exactly feature mentioned in my statement above became
deprecated in C++11?

>
>


-Pavel
 
Reply With Quote
 
 
 
 
Balog Pal
Guest
Posts: n/a
 
      06-04-2012
"mike3" <(E-Mail Removed)>
>> >The ability to make such a determination is extremely rare, including
>> >for invalid input. Exceptions should be the normal response to
>> >invalid input to a function, including to invalid input supplied by
>> >the outside world.

>
>> That opens slippery slope for mixing program logic errors with
>> environmental
>> factors outside our control.

>


>So does this mean that we should prefer _error codes_, not exceptions, and
>reserve exceptions only for the _rare_ "environmental" error? Now I'm even
>more
>confused. How do you handle a failing constructor?


No, it just means that for the case where the program detects it is in
*unexpected* state, you don't throw neither return a code, but halt the
program right then and there, avoiding to mess up even more.

Error handling -- by whatever means -- is to handle expected conditions.

So there is a fundamental difference.

Say you have a std::vector and use it by index, you keep the index in the
[0, size()-1) range, always. Your code will never generate illegal index to
call op[]. If somewhere the supposed index is coming from some unknown
source, like read from a file or socket, you first do the gating. That will
either prevent getting to the indexing operation, or reset the incorrect
input to usable range.

Correct index is PRECONDITION of op[], that is properly specified. You
violate that and get undefined behavior. So you just don't get there.

And it applies to anything you design. Including ctors. What you consider
precondition, you just expect. If having preconditions met the ctor still
can fail, you have limited options: you either throw or construct to some
special state. Id you're okay with something like 'empty' or 'default', it
may fly. If you must set an 'invalid' state, such class will be major PITA
to use.

 
Reply With Quote
 
Balog Pal
Guest
Posts: n/a
 
      06-04-2012
"Pavel" <(E-Mail Removed)>
> Balog Pal wrote:
>>
>> "Pavel" <(E-Mail Removed)>
>>
>>> 2. C++ functions with exception specifications. A programmer is reminded
>>> about
>>> possible error conditions if s/he has function prototype in front of him
>>> or
>>> her while coding the call.

>>
>> The what? Did you read what those do in C++? Or typical rationalt to
>> (not) use
>> them, ie. at Boost with cool explanation? Or at MS that just refused to
>> implement this braindead feature? Looking ahead in time, as in C++11 this
>> feature became deprecated.


> I am sorry, what exactly feature mentioned in my statement above became
> deprecated in C++11?


(dynamic-)exception specifications. 15.4p17

The new noexcept-specification is certainly good for its purpose, but being
binary doesn't fit your decription.

 
Reply With Quote
 
Pavel
Guest
Posts: n/a
 
      06-04-2012
Adam Skutt wrote:
> On Jun 3, 7:07 pm, Pavel
> <(E-Mail Removed)> wrote:
>> Adam Skutt wrote:
>>> On Jun 3, 4:45 pm, Rui Maciel<(E-Mail Removed)> wrote:
>>>> Adam Skutt wrote:
>>>>> The entire point of exception handling is that if you cannot (or need
>>>>> not) respond to the condition, you pretend that it does not exist.

>>
>>>> A while ago I was working on an application that used Qt for the GUI and
>>>> Eigen for linear algebra. Long story short, under some circumstances Eigen
>>>> threw an exception and Qt caught it. And when Qt caught it, it terminated
>>>> the process.

>>
>>>> So, if you follow your own advice then you better be prepared to deal with
>>>> its consequences.

>>
>>> Qt clearly says on its wrapper that it is not exception safe and has
>>> said so since its inception AFAIK. Broken software doesn't really
>>> impact my position

>>
>> Reality check #1:
>> Good luck saying it to your manager who is asking your to fix the "broken"
>> software.

>
> Yes, I agree. If you know you're using Qt, then your design is broken
> if it doesn't consider its lack of exception safety.

It is as mine as your design. I do not recall defending this broken design.
Someone made a mistake in the past and now your manager asks you to maintain
their code.

> People who
> blindly mix exception-safe and unsafe code deserve what they get.

No, in this Reality Check #1 case *you* will get what *they* deserved. And after
getting it several times (from mistakes of several different people), you will
probably not recommend Eigen for using in your next project (if asked). (unless
you start to enjoy "getting it" every time, that is).

>
> However, the mere fact that exception unsafe code exists in the world
> isn't justification for avoiding exceptions, on the off possibility
> someone might use your code with such broken software.
>
>>
>> Reality check #2:
>> According to your willingness to "kick the can down the road" (that is, to
>> define top-level library APIs throwing exceptions), you could be an author of
>> that Eigen package (imagine that Eigen is perfect in all other regards so you
>> don't have a reason to disown it). Then, good luck attempting to sell a new
>> version to the Rui's company after they ask you for support on the above case
>> and *you tell your users that they are at fault for writing broken software and
>> not RTFMing on Qt*.

>
> Except I wouldn't do that, if I was going to get paid to write
> wrappers to convert the exceptions to error codes I would happily do
> so.

Except you will hardly get to write those wrappers because your API is already
in use and so your business-offer to write wrappers will likely be rejected on
the grounds of not having budget to do major changes in already almost-working
client code. You will have to write the wrappers on your own dime and then
market your library to other customers -- in which you may succeed but it will
cost you more than if you predicted the situation and provided the conservative
API from the outset.

Absent pay though, it's his problem and he can keep the broken
> pieces.
>
>>
>> Sarcasm aside, products should be designed for real rather than ideal world, and
>> you imperfect user (who incidentally pays your bills) tends to live in the former.
>>

>
> And if they want Qt support upfront then they should specify it as a
> requirement.

In real world, they never will. They will just assume it will work unless you
tell them otherwise. In this particular case they will have good reason for
that: Eigen is a low-level math library -- why in the world should it be
incompatible with Qt?

Also, it was *your design decision* to use that feature with which a useful
library is incompatible. If you have a competitor marketing an otherwise
equivalent but non-throwing library, they won and you lost.

Designing for the real world does not involve
> considering every last possible and framework that could interact with
> my software, as such a thing is simply not possible.

But using features conservatively is possible and it would have saved your day
in Reality check #2.

-Pavel
 
Reply With Quote
 
Pavel
Guest
Posts: n/a
 
      06-04-2012
Balog Pal wrote:
> "Pavel" <(E-Mail Removed)>
>> Balog Pal wrote:
>>>
>>> "Pavel" <(E-Mail Removed)>
>>>
>>>> 2. C++ functions with exception specifications. A programmer is reminded about
>>>> possible error conditions if s/he has function prototype in front of him or
>>>> her while coding the call.
>>>
>>> The what? Did you read what those do in C++? Or typical rationalt to (not) use
>>> them, ie. at Boost with cool explanation? Or at MS that just refused to
>>> implement this braindead feature? Looking ahead in time, as in C++11 this
>>> feature became deprecated.

>
>> I am sorry, what exactly feature mentioned in my statement above became
>> deprecated in C++11?

>
> (dynamic-)exception specifications. 15.4p17
>
> The new noexcept-specification is certainly good for its purpose, but being
> binary doesn't fit your decription.

No, I meant dynamic exception specifications. Thanks for pointing this out -- I
was thinking they only deprecate the specified behavior on violations, making it
UB in the future.

I have not used them due to performance issues; but they gave at least some
clues. As my list is all about giving programmer a clue, they still belong to my
list at that place #2, I guess.

-Pavel
 
Reply With Quote
 
Adam Skutt
Guest
Posts: n/a
 
      06-04-2012
On Jun 3, 9:46*pm, Pavel
<(E-Mail Removed)> wrote:
> Adam Skutt wrote:
>
> > And if they want Qt support upfront then they should specify it as a
> > requirement.

>
> In real world, they never will. They will just assume it will work unlessyou
> tell them otherwise. In this particular case they will have good reason for
> that: Eigen is a low-level math library -- why in the world should it be
> incompatible with Qt?
>


Because it can potentially throw exceptions[1] and Qt is mostly
exception unsafe. You're tilting at windmills, this concern merits
about the same consideration as: "Why won't my C++ compiler compile
Java code?" This particular facet of Qt requires serious
consideration at every level and seriously impacts the code you will
write and the libraries you will use.

Exceptions are a mandatory feature of C++. They're used by the
standard library. That alone is sufficient to justify their usage in
any random library. Avoiding exceptions means avoiding most of the
standard library, which is plainly too high of a burden for most
libraries and applications. It also severely limits the kind of code
that be written, especially when templates are in play.

At any rate, I see no point in discussing this with you further if
your cost/benefit compass is so skewed to believe that the standard
library made the wrong decision.

> But using features conservatively is possible and it would have saved your day
> in Reality check #2.


If we take that to its final conclusion, then we should never write C+
+ at all and only write C code that can be compiled with a C++
compiler. Which actually seems to be what you're secretly trying to
say, without actually saying it.

Adam

[1] I should, at this point, note that Eigen itself uses asserts
internally for the most part, though overriding those to throw
exceptions is pretty easy. However, it can still trip those
exceptions that happen in the C++ runtime (e.g., std::bad_alloc) or
that are caused by the objects it holds (like the STL), which will
create problems for Qt.
 
Reply With Quote
 
Pavel
Guest
Posts: n/a
 
      06-04-2012
Balog Pal wrote:
> "Pavel" <(E-Mail Removed)>
>> Exactly. Now you are at last talking about the subject of my post. If one of
>> your requirements is to log every error in a particular manner, it is
>> significantly more labor-consuming to do that "walking ever line of code"
>> (which you will have to do, no matter how much you hate the idea) with the
>> exception-based API than with error code-based API.

>
> IMO&IME obsession with logging normally lurks in rotten projects, and is a big
> player in the rot. Efforts could be put to write correct code instead, and the
> kind that is light, focused, readable.

Efforts has to be put first and utmost to satisfying the customer. Logging is a
user (and sometimes, regulatory, too) requirement, not a design decision left up
to the software engineer.

Also, correctness of the code has little to do with the necessity of the
logging: the error logging is mainly for the error conditions caused by input
data and computational environment (broken connections, corrupted or full disk
drives etc).

> Then it will just work. (You can still
> log the few enviromental events

exactly

> causing exit

why should an application exit if a single connection got stale or a single
transaction of a single user invalidated his or her session (just few error
conditions of those that are usually to be logged)?

at a central location, and without
> care which operation was involved...)
>
> But if you need something like that I still don't see why is it that hard. I'd
> create a simple RAII class that you put as local at every function entry, call
> its OK() at the exit. In case of unexpected exit it emits a log line from dtor.

Why would you complicate and pessimize the main code path of the program? If
error is not created 99.999% of the times, why would I make my user to create,
pass and destroy that object on every function call? (It will also have to check
the error condition; but that has to be done with error codes, too, so I did not
count it as pessimization).

> You can simply add checkpointing or insert info on actions you will do. I guess
> i could write a simple macro to automate most of the magic. Leaving way less
> clutter than the retcodes version.

How the version with return code whose processing is wrapped in macros will
leave more cluter than RAII version of the same?

>
>> It is instructive that in some libraries designed for critical applications by
>> serious ISPs (e.g. IBM's MQ Series C API), the error codes were returned in
>> output parameters.

>
> That sounds weird. Can you explain why is that good? With the usual way I can
> make the functions CHECKRETURN and use the compiler to flag places where return
> was ignored, without extra effort. I'm not aware of similar support on arbtrary
> arguments used for output.
>
>> A programmer using such API does not have a chance to fully ignore error
>> conditions because s/he needs to define a variable (sometimes more than one)
>> to hold error codes.

>
> With a C API? how hard it is to pass NULL for the output param? And even if you
> force to pass a variable what makes the code look at it more than the return code?

Hey, we are not talking about *willingly* shooting yourself in a leg. What I
mean is that the programmer will have to type in that NULL (actually in C++ it
is rather 0 or that nullptr beast). If s/he does not know or think why s/he is
typing stuff, there is no technical solution to this problem.

Programmers are, in general, not dumb, but they are people and they forget
things and they are sometimes somewhat sloppy. It is forgetfulness and
sloppiness that is responsible for not checking those error codes or not
catching those exceptions. A timely reminder helps a forgetful programmer and
can sometimes control light forms of sloppiness.

>
>
>


-Pavel
 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      06-04-2012
On 06/ 4/12 12:56 PM, Balog Pal wrote:
> "mike3"<(E-Mail Removed)>
>>>> Is it a good idea to default to exceptions for errors, and then if after
>>>> you start actually using the code, it looks like an error code is more
>>>> appropriate, to use that instead?

>>
>>> Yes. As I mentioned for some operations there's a need for both forms.
>>> Fortuneately it's not hard to write converters in either direction, and
>>> then
>>> clients can use the better-suited variant.

>
>> So then you _do_ need a translation layer than translates error codes
>> to exceptions and exceptions to error codes, and thus need a 1-to-1
>> correspondence between the two, with exception classes for every error
>> code in your error code enum

>
> I wonder how you arrived at that conclusion.


I'm almost certain he his being deliberately obtuse.

--
Ian Collins
 
Reply With Quote
 
mike3
Guest
Posts: n/a
 
      06-04-2012
On Jun 3, 8:50*pm, Ian Collins <(E-Mail Removed)> wrote:
> On 06/ 4/12 12:56 PM, Balog Pal wrote:
>
>
>
> > "mike3"<(E-Mail Removed)>
> >>>> Is it a good idea to default to exceptions for errors, and then if after
> >>>> you start actually using the code, it looks like an error code is more
> >>>> appropriate, to use that instead?

>
> >>> Yes. As I mentioned for some operations there's a need for both forms..
> >>> Fortuneately it's not hard to write converters in either direction, and
> >>> then
> >>> clients can use the better-suited variant.

>
> >> So then you _do_ need a translation layer than translates error codes
> >> to exceptions and exceptions to error codes, and thus need a 1-to-1
> >> correspondence between the two, with exception classes for every error
> >> code in your error code enum

>
> > I wonder how you arrived at that conclusion.

>
> I'm almost certain he his being deliberately obtuse.
>


???

How did I arrive at this conclusion? I interpreted the bit about
"converters in
either direction" to mean there needs to exist a bidirectional
exception <->
error code translation layer. That it needs to be 1-1 was because I'm
probably
having my vision colored by my current system. I bet my current-system-
colored
goggles need to come off, but then I'd need some more info to
understand
just what kind of thing he had in mind.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
How to use file I/o codes with form and controls codes Allen ASP .Net 1 12-03-2007 12:04 AM
Should I use exceptions instead of error codes? mike3 C++ 14 11-17-2007 10:04 PM
Virtual Key Codes, Scan Codes and ASCII Codes in C gj_williams2000@yahoo.co.uk C Programming 2 08-20-2005 11:04 AM
RegEx replace of html codes to ascii codes Greg -- ASP .Net 4 08-09-2005 07:27 PM
Exceptions vs. Error Codes Shane Groff C++ 8 10-10-2004 05:05 PM



Advertisments