Error codes vs. exceptions

B

Balog Pal

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.
 
P

Pavel

Balog said:
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
 
B

Balog Pal

mike3 said:
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.
 
B

Balog Pal

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.
 
P

Pavel

Adam said:
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.


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. ;)


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
 
P

Pavel

Balog said:
(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
 
A

Adam Skutt

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.
 
P

Pavel

Balog said:
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?
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.


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
 
M

mike3

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.
 
P

Pavel

Adam said:
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?

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?"
I honestly cannot see any similarities. C++ compiler has never compiled Java
code but the app of your customer happily worked on Qt until they were
unfortunate enough to buy and start using your Eigen.
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.
They are just hammers in their rightful search of nails, aren't they? A hammer
is a mandatory tool to be learned by a carpenter. That is not, however,
sufficient to justify its use in any random of work.
Avoiding exceptions
Mooting the point again? What do you mean by "avoiding exceptions" and how is it
related to my position?

means avoiding most of the
standard library,
which is plainly too high of a burden for most
libraries and applications.
I am glad we agree on this one.
It also severely limits the kind of code
that be written, especially when templates are in play.
It may or may not be true but is completely irrelevant to my point.
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.
The authors of the standard library made a lot of good decisions and some
not-so-good decisions. IMHO, most of not-so-good decisions were made when people
were motivated by the natural desire to demonstrate "right usage" of new "cool"
features of the language (such as exceptions and operator overloading in case of
iostream library) rather than by careful analysis of user requirements.

That "Compatibility Features" application D of the standard (all versions) is a
good graveyard of some but not all of those ideas.
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.
As always, you are replying to your own statements rather than mine. As I wrote
in my very first post on the subject, I am discouraging throwing exceptions
across library boundaries, not within them. How would I throw and catch
exceptions within libraries in C?

Oh yeah, but because I have that "secret agenda" (in your imagination), I would
probably say so anyway, wouldn't I?
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.

-Pavel
 
M

mike3

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.

But to me it seemed you were talking about a conversion _between error
codes
and exceptions_. Was I wrong? You mentioned "converters in either
direction"
and I interpreted this as meaning you need a bidirectional converter
of
error codes <-> exceptions. It's probably based on me interpreting
this stuff
through the lenses of my current system -- NOT a good idea, probably!
-- and
that's what I'm seeing. Because I was not sure what you meant by
"converters
in either direction" and filled it in with what I _thought_ you meant.
That a 1-1
correspondence, etc. is needed is because how else do you do the
translation
in two directions in the example I gave (see below about the "out of
range"
stuff, but you say those kind of range checks are probably not
necessary, at
least, not the way I have them with exceptions/error codes, but should
be
"assert" if this thing would be in range in a working program, i.e. if
it's
out of range that signals a programmer error (as from what I can tell,
it
likely would in many cases in this program.).).
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.


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

Sounds like a good idea.
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.

What do you mean by "library"? This is not a library I'm developing,
just making
a regular program. Nor am I asking about return codes from a library,
but rather
from functions within the program.
 update the error code list and add a new exception
class and also update the translator.


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

Watch the baton not the runners.

See below, I give an explanation there.
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.

OK. But what about for user input? Oh, but wait, then we'd use an
error code.
Never mind.
Why would you want the reverse translation?

You said "converters in either direction". I _interpreted_ that to
mean a need
for reverse translation. Also,

You: "In usual good code 95% of catch() blocks just do a conversion to
some
different exception or a return code. "

"conversion to ... a return code".
....


In so many words.


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.


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

I'm curious: what do you mean by "made them up"? The problems I
mention are ones that exist in the current system. Correction: What
I said was based on thinking about this stuff in terms of the current
system. What I have right now is a system with error codes and
exceptions, corresponding 1-to-1 with each other, so that we can
"translate" back and forth between the two seamlessly, without loss
of information in either direction. I had a single "exception" type
that received the error code as a type field. Thus making for a
straightforward translation (to translate exception to code, just
extract code, to translate code to exception, just create and
throw exception object with code passed via the constructor).

But now I've heard, from reading Stroustrup's "bible" more, that it
seems like a better idea to have a number of different exception
classes (and in a hierarchy, too, so one can group them into
related groupings and catch all those from a group with a single
"catch"), and I've also seen posts on various sites that one
shouldn't use a monolithic exception type and that "typefields
are bad" (this is also in the "bible". And I can say why they're
bad, too -- e.g. multiple switch statements = harder to maintain,
you can forget to put stuff in = bugs, also the compiler cannot
check the type. All that is in the "bible", which I have right
here on my desk.). Then we get the need to have switch
statements to select exception classes to throw depending
on error code and need error codes wired into the exception
classes to translate back.

Seeing the problems, I thought it is time for a new system.
 
G

Guest

something may have gone wrong with the attributions

what if you have to do some specialised cleanup action?
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/
[3]. If you're doing something else, then you're designing your code
entirely incorrectly. Such behavior is the height of
irresponsibility, because it is a fool's errand. C++ libraries need
not declare every exception they throw,

...but they should, or at least declare that they throw or don't
throw.
so without walking every line
of code of every library you use (directly or indirectly), one cannot
even accomplish what you say should be done.

This is the problem I have with exception handling: you CANNOT
ignore exceptions. You must in some manner handle the possibility,
else your program ENDS! Handling minor, recoverable, errors with
throwing exceptions is like police shooting jaywalkers.

Often, how you recover from an error depends on the specific error
information. If you "try" each individual function that might throw,
you might as well have error codes. The larger the "try" block, the
more difficult to isolate and repair/recover from the damage becomes.

So if I wind up using a library written by someone who throws an
exception for every incorrect condition, large or small, I have to
handle all of them or "throw the baby out with the bath water."

this sounds really wrong. Could you give a short example of code that has to do this? I usually find the code looks like this:-

void perform ()
{
try
{
action1 ();
action2 ();
action3 ();
}
catch (exception& e)
{
error_actions()
}
}

in other words *all* of actionN must succeed for the function towork properly.
 
I

Ian Collins

something may have gone wrong with the attributions


what if you have to do some specialised cleanup action?

Use stack unwinding to take care of that.

By the way, mixing direct and indirect responses in one post is confusing.
 
B

Balog Pal

Pavel said:
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.

Logging return codes of library calls and content of exceptions?
I seriously doubt any kind of regulation would deal with that. I'm skeptic
about customer too.

Real logging is indeed often a requirement, but it's a completely different
beast -- you write a log of action taken by the program, changes of
database, etc. It goes on much higher level.

The fragments we dscussed here, that ask actions in error handling branches
close to call places is more like TRACE, and if ever looked after, serves to
find problems with the program implementation.
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).

And those fit pretty well at the top level actions, and need not do anything
but write out exception.what() with a timestamp.

I.e. all you want to see in log is "OS error #??? 'disk full' on savig file
'/etc/bar'". no interest in which byte failed in which
function/source/line/whatever.
Why would you complicate and pessimize the main code path of the program?

I didn't say you should, only that it can be done if requirement emerges --
possibly just as a drop-in to corner a problem detected by a test. And the
point is that it can be done *without* messing up the code path and create
visible conditional or try blocks.
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).

As the state of the object is just a bool maximum an int, so I'm sure you
could not measure its presense in a real application. (On PCs the
performance is determimned by memory cache unless you stall or something
even slower... current processors stall 50-100 ticks on any cache miss. ALU
operations come practically free. )
How the version with return code whose processing is wrapped in macros
will leave more cluter than RAII version of the same?

Just write the code and look at it. Unless you can show me a return code
processing without a sigle IF or condition.
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.

You evaded the question. The checkreturn attribute flags exactly what it
suposed to: an accidental overlook. How an out param wants to be better?
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.

I agree with that, that's why I don't get the point of this "improvement".

You turn on the checkreturn warning and add /Werror (that we normally use
unless have some very hostile unkillable warnings), and presto -- failing
build is quite a reminder for the forgetful, isn't it?
 
M

Martin B.

It's senseless to cater to such senseless micro-optimizations unless
you must. Modern C++ implementations don't incur execution overhead
unless an exception is actually tossed. I assume you don't use
libraries that use virtual functions as well because of the same
potential problem?

I agree that the overhead of the actual exception scaffolding is
negligible in the vast majority of cases.

Still, I think you generally miss the point. When you write code, you
cannot know a-priori whether the *failure* case for a certain (library)
function is in a performance critical code path. So if a (set of)
certain (library) function(s) reports all failures/errors via
exceptions, this can introduce a significant performance overhead for a
critical code path where the failure of a certain function is actually
expected/probable.

cheers,
Martin
 
B

Balog Pal

Scott Lurndal said:

We had a pretty long thread here titled 'We do not use C++ exceptions at
Google'. No, it was on .moderated, early 2009.

The conclusion was that this guideline is a major WTF, and most likely due
to Google got locked in with a huge rotten codebase. And selection of staff
too, with that rule not trained to know about exception safety and the rest.

A plenty of excellent C++ programmers just refuse to work with that, so they
are left with the rest

It hardly means anything beyond that.

Too bad I didn't save the dox at the time. The current one looks even more
explicit admitting that they fouled up their environment and decided to stay
in darkness forever.
 
B

Balog Pal

Martin B. said:
Still, I think you generally miss the point. When you write code, you
cannot know a-priori whether the *failure* case for a certain (library)
function is in a performance critical code path. So if a (set of) certain
(library) function(s) reports all failures/errors via exceptions, this can
introduce a significant performance overhead for a critical code path
where the failure of a certain function is actually expected/probable.

In which (higly speculative) case you drop use of that library as one unfit
for your particular purposes.

Guess it will be the first case someone got hosed by a 3rd party tool
distributetd binary-only, so will worth a full article, maybe even a Ph.D.
dissertation.

What's next?
 
P

Pavel

Balog said:
Logging return codes of library calls and content of exceptions?
I don't think you have read my post. Please re-read it around the word "map".
I seriously doubt any kind of regulation would deal with that. I'm skeptic about
customer too.

Real logging is indeed often a requirement, but it's a completely different
beast -- you write a log of action taken by the program, changes of database,
etc. It goes on much higher level.
"It goes" at the required level.
The fragments we dscussed here, that ask actions in error handling branches
close to call places is more like TRACE, and if ever looked after, serves to
find problems with the program implementation.
I did not discuss tracing.
And those fit pretty well at the top level actions, and need not do anything but
write out exception.what() with a timestamp.
Meaningful recovery from input data integrity errors need context, e.g. who, why
(in what context) and how submitted the query. The data processing engine itself
often does not know the answers and cannot encode them to what().
I.e. all you want to see in log is "OS error #??? 'disk full' on savig file
'/etc/bar'". no interest in which byte failed in which
function/source/line/whatever.
I might want to see which file could not be written because disk is full, then
evaluate the impact and dispatch the situation accordingly (restart myself, kill
some other process that reserves much space but can be safely killed to be
restarted later, notify this or that support level etc).
I didn't say you should, only that it can be done if requirement emerges --
possibly just as a drop-in to corner a problem detected by a test. And the point
is that it can be done *without* messing up the code path and create visible
conditional or try blocks.


As the state of the object is just a bool maximum an int, so I'm sure you could
not measure its presense in a real application. (On PCs the performance is
determimned by memory cache unless you stall or something even slower... current
processors stall 50-100 ticks on any cache miss. ALU operations come practically
free. )
passing extra arguments hits memory and hence cache, both for read and write at
that.
Just write the code and look at it. Unless you can show me a return code
processing without a sigle IF or condition.
You don't read. I already told both "my" and "your" code will have to check the
error condition). "My" code could be (unless I use macros):

if (Error error = apiCall()) {
processError(error /* , context */);
return;
}

What is your code?


You evaded the question.
You mean -- how hard it is to pass NULL? Easy. So?

The checkreturn attribute flags exactly what it suposed
to: an accidental overlook.
Unless I am missing anything, checkreturn attribute is not standard C++?
How an out param wants to be better?
I have never said they were better. They are more explicit, but carry extra code
complexity and performance costs. Tradeoffs are everywhere. What I wanted to
illustrate is a conservative choice made by a solid firm that knows a thing or
two (actually, all there is to know) of the requirements of big enterprise-level
applications.
I agree with that, that's why I don't get the point of this "improvement".
You agree that timely reminder sometimes helps but don't see the point? You are
confusing me.
You turn on the checkreturn warning and add /Werror (that we normally use unless
have some very hostile unkillable warnings), and presto -- failing build is
quite a reminder for the forgetful, isn't it?
I am not sure it is a standard C++ feature to warn about unused return value on
selected functions only (especially if the return value is an object of a class
which is sometimes true with error code). I agree though that this would help in
approximately same manner as a parameter -- as long as the option/attribute
stays "on" in API client's build system -- which API author certainly does not
control.

-Pavel
 

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

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top