473,836 Members | 1,562 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Checking return values for errors, a matter of style?

I've written a piece of code that uses sockets a lot (I know that
sockets aren't portable C, this is not a question about sockets per
se). Much of my code ended up looking like this:

Expand|Select|Wrap|Line Numbers
  1. if (function(socket, args) == -1) {
  2. perror("function");
  3. exit(EXIT_FAILURE);
  4. }
I feel that the ifs destroy the readability of my code. Would it be
better to declare an int variable (say succ) and use the following
structure?

Expand|Select|Wrap|Line Numbers
  1. int succ;
  2.  
  3. succ = function(socket, args);
  4. if (succ == -1) {
  5. perror("function");
  6. exit(EXIT_FAILURE);
  7. }
What's considered "best practice" (feel free to substitute with: "what
do most good programmers use")?
Jul 31 '06
66 3655
On 2006-08-01, Keith Thompson <ks***@mib.orgw rote:
Andrew Poelstra <fa**********@w p.netwrites:
>On 2006-07-31, Johan Tibell <jo**********@g mail.comwrote:
[...]
>>What's considered "best practice" (feel free to substitute with: "what
do most good programmers use")?

It really depends on what your target is. In most of my code, I'm
thinking of removing all the checks for stuff like malloc(10) because
there is only a 0.02% chance that I'll be porting my code to a
non-desktop machine where memory is scarce.

OTOH, if you work for a company that deals in all sorts of systems, it
may be worthwhile to have a meaningful error message printed in the case
of problems.

It's not so much a matter of style as it is a matter of practibility:
your code must be robust, but it should also be easy to read. Nowadays
programs targeted at home computers or servers can assume that you'll
have a 99.99% success rate on a functioning system when allocating
memory < 1Kb.

Why would you want to settle for 99.99% when you can get 100%?

It takes only one failure to ruin your whole day.
Because that tiny percentage is the difference between
p = malloc (sizeof *p * q);

and
p = malloc (sizeof *p * q);
if (rv = !!p)
{
/* Rest of function here. */
}

Those ifs nest up and it becomes a pain to manage them. I prefer not to
have multiple returns because they annoy me; if I want to know what a
function returns, I like to skip to the end. If I see a "return 0" I
know that I either have a foolproof function, or I have to go and find
other return values elsewhere in the code. Better to have a
return rv; /* rv is 0 on success, or -1 on error (bad memory or file) */

Another idea would be to create a varadic function that checks multiple
memory allocations:
if (chk_mem (p, q, r, s, t) && chk_file (inf, outf))
{
/* Rest of function is happy. */
}

Hmm. I'm not sure whether to be sad that my readability argument is
falling apart, or happy that I'm learning better code design.
Also, I have an diagnostic library that will send errors to any stream
specified. So, if a user has a problem with a 12-byte allocation and the
rest of the system is for some reason working fine, I can tell him to
run myprog --debug and send me the output of myprog.log.

There's an extra step in there where he's emailing me a log, but
otherwise the communication would be the same; I'd have to tell
him to increase his swap space or to run fewer programs. (I'm
assuming here that a bad allocation will give me a nice GPF or
segfault; this isn't always true and is one of the most dangerous
assumptions I tend to make.)

--
Andrew Poelstra <website down>
To reach my email, use <email also down>
New server status: I've figured out how the case opens.
Aug 1 '06 #11
Andrew Poelstra <fa**********@w p.netwrites:
On 2006-08-01, Keith Thompson <ks***@mib.orgw rote:
>[...]
Why would you want to settle for 99.99% when you can get 100%?

It takes only one failure to ruin your whole day.

Because that tiny percentage is the difference between
p = malloc (sizeof *p * q);

and
p = malloc (sizeof *p * q);
if (rv = !!p)
{
/* Rest of function here. */
}

Those ifs nest up and it becomes a pain to manage them. I prefer not to
have multiple returns because they annoy me; if I want to know what a
function returns, I like to skip to the end. If I see a "return 0" I
know that I either have a foolproof function, or I have to go and find
other return values elsewhere in the code. Better to have a
return rv; /* rv is 0 on success, or -1 on error (bad memory or file) */
[...]

If you just abort the program on a malloc() failure, there's no reason
for the level of nesting to get out of hand.

p = malloc(sizeof *p * q);
if (p == NULL) {
fprintf(stderr, "malloc failed\n");
exit(EXIT_FAILU RE);
}
/* Rest of function here */

It's not a *great* way to handle the error, but it's better than
ignoring it.

Or, as I suggested, write a wrapper:

void *my_malloc(size _t size)
{
void *result = malloc(size);
if (result == NULL) {
fprintf(stderr, "malloc failed\n");
exit(EXIT_FAILU RE);
}
else {
return result;
}
}

....

p = my_malloc(sizeo f *p * q);

The alternative is to ignore allocation failures and risk undefined
behavior.

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Aug 1 '06 #12

Andrew Poelstra wrote:
On 2006-08-01, Keith Thompson <ks***@mib.orgw rote:
Andrew Poelstra <fa**********@w p.netwrites:
It really depends on what your target is. In most of my code, I'm
thinking of removing all the checks for stuff like malloc(10) because
there is only a 0.02% chance that I'll be porting my code to a
non-desktop machine where memory is scarce.
Why would you want to settle for 99.99% when you can get 100%?
>
Also, I have an diagnostic library that will send errors to any stream
specified. So, if a user has a problem with a 12-byte allocation and the
rest of the system is for some reason working fine, I can tell him to
run myprog --debug and send me the output of myprog.log.
This won't work at all. If I run your program and get a segfault
because of a memory error, when I run your diagnostic there's
a very good chance that the problem won't re-occur. It will
end up being an error that happens .01% of the time, but
never when I'm running the diagnostic tool! Pretty quickly,
I'll just decide that your code is unstable and I'll stop using
it. And if I ever look through the source and see unchecked
mallocs, I'll stop using it immediately! Putting a wrapper
around malloc ( "xmalloc" and "Malloc" are the two common
names I've seen, "my_malloc" has been mentioned in this
thread) that aborts on error is a much better approach, if
for no other reason than keeping your users happy.
At run time,I'd much rather see:
"Out of memory", than "Segmentati on fault".

Aug 1 '06 #13

Frederick Gotham wrote:
Johan Tibell posted, w.r.t. checking return values:
What's considered "best practice" (feel free to substitute with: "what
do most good programmers use")?

Have you considered something like:

void Assure(int const i)
{
if(-1 == i)
{
perror("functio n");
exit(EXIT_FAILU RE);
}
}
That's nice. How about:

#define Assure(x) if (!(x)) {fprintf(stderr , "In %s:%s " #x "
failed\n",\
__FILE__, __func__); exit(EXIT_FAILU RE);}
>
And then putting something like the following in your code:

Assure( function(socket ,args) );
Which allows slightly more flexibility:
Assure (function(a,b,c ) == expected_value) ;

Aug 1 '06 #14
Andrew Poelstra said:

<snip>
It's not so much a matter of style as it is a matter of practibility:
your code must be robust, but it should also be easy to read.
Your code is not going to be robust if it doesn't check whether a request
for an external resource was successful. I agree it should be easy to read,
but that doesn't mean leaving the code out!
Nowadays
programs targeted at home computers or servers can assume that you'll
have a 99.99% success rate on a functioning system when allocating
memory < 1Kb.
Programmers who make such an assumption should not be writing for the home
market or the server market. They should be writing in crayon on droolproof
paper.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Aug 1 '06 #15
Johan Tibell wrote:
I've written a piece of code that uses sockets a lot (I know that
[...]
What's considered "best practice" (feel free to substitute with: "what
do most good programmers use")?

Following style makes it clear from reading point of view,

/********/
#define RET_CODE_SUCCES S 1
#define RET_CODE_FAILUR E -1

....

if (RET_CODE_FAILU RE == function(socket , args);) {
perror("functio n");
exit(EXIT_FAILU RE);
}
/********/

As far as storing the return value in a variable is concerned, if you
are not going to use it, there is no need to store it. If you want to
check for the returned value during debugging, you can step-in to that
function.

Aug 1 '06 #16

Andrew Poelstra wrote:
On 2006-08-01, Keith Thompson <ks***@mib.orgw rote:
Andrew Poelstra <fa**********@w p.netwrites:
On 2006-07-31, Johan Tibell <jo**********@g mail.comwrote:
[...]
>
Because that tiny percentage is the difference between
p = malloc (sizeof *p * q);

and
p = malloc (sizeof *p * q);
if (rv = !!p)
{
/* Rest of function here. */
}

Those ifs nest up and it becomes a pain to manage them.
Your customer pulling his hair on a segmentation fault while doing an
intense calculation or running a major server is even a bigger pain,
for him and for your repute.

Another idea would be to create a varadic function that checks multiple
memory allocations:
if (chk_mem (p, q, r, s, t) && chk_file (inf, outf))
{
/* Rest of function is happy. */
}
What if you want to do some thing if memory allocation fails at one
point and some thing else if it fails at some other point?

Hmm. I'm not sure whether to be sad that my readability argument is
falling apart, or happy that I'm learning better code design.
Better code design and readability, IMHO, complement each other.

There's an extra step in there where he's emailing me a log, but
otherwise the communication would be the same; I'd have to tell
him to increase his swap space or to run fewer programs.
One of the worst pieces of advice I have ever heard. Do you work for,
ahem, M$?

Aug 1 '06 #17
On 2006-08-01, Richard Heathfield <in*****@invali d.invalidwrote:
Andrew Poelstra said:
>It's not so much a matter of style as it is a matter of practibility:
your code must be robust, but it should also be easy to read.

Your code is not going to be robust if it doesn't check whether a request
for an external resource was successful. I agree it should be easy to read,
but that doesn't mean leaving the code out!
What exactly /would/ be the way to do such a thing? I ask you because
you don't like multiple returns or the break statement, both of which
would be a typical response.
>Nowadays
programs targeted at home computers or servers can assume that you'll
have a 99.99% success rate on a functioning system when allocating
memory < 1Kb.

Programmers who make such an assumption should not be writing for the home
market or the server market. They should be writing in crayon on droolproof
paper.
Being as every other post was pretty much exactly as insulting as this,
I'd say that I wasn't not wrong on any minor point! I'm glad that I haven't
had the chance to make these foolhardy changes to my actual code yet.

I've written a new interface to my error library so that it will be able
to handle memory failures gracefully, log to a runtime-determined file,
check for bad files or memory, and ensure that a proper message reaches
the user if it can't go on.

--
Andrew Poelstra <website down>
To reach my email, use <email also down>
New server time-to-be-up: Today
Aug 1 '06 #18
On 2006-08-01, Andrew Poelstra <fa**********@w p.netwrote:
I wasn't not wrong on any minor point!
Seems it's not just the 2AM folks getting their "not"s mixed up! I meant
"I wasn't wrong on some minor point!"

--
Andrew Poelstra <website down>
To reach my email, use <email also down>
New server ETA: 42
Aug 1 '06 #19
On Tue, 01 Aug 2006 00:19:00 GMT, Andrew Poelstra
<fa**********@w p.netwrote:
>It's not so much a matter of style as it is a matter of practibility:
your code must be robust, but it should also be easy to read. Nowadays
programs targeted at home computers or servers can assume that you'll
have a 99.99% success rate on a functioning system when allocating
memory < 1Kb.
You've forgotten the rule of computing probability - if there's one
chance in a million, it happens every second.

You must have written some of the code for Windows.

--
Al Balmer
Sun City, AZ
Aug 1 '06 #20

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

Similar topics

16
2640
by: lawrence k | last post by:
I've made it habit to check all returns in my code, and usually, on most projects, I'll have an error function that reports error messages to some central location. I recently worked on a project where someone suggested to me I was spending too much time writing error messages, and that I was therefore missing the benefit of using a scripting language. The idea, apparently, is that the PHP interpreter writes all the error messages that are...
0
9818
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...
0
9668
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10843
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
10546
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10589
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
9371
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...
0
6978
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();...
0
5648
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
2
4015
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.