By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,984 Members | 1,040 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,984 IT Pros & Developers. It's quick & easy.

What's The Best Practice Defining Error Codes in C

P: n/a
Hi,

I would like to have someone comments on what's the best practice
defining error codes in C.
Here's what I think:
solution A:
using enum
pros: type safe. better for debug (some debugger will show the name
not only the value)
cons: enum can not be forward declared which makes all error codes
couples together with the error code type ( enum )

Solution B:
using #define
pros: decouple, error codes could be defined in different .h file
cons: macro is bad. no type safe

Solution C:

typedef struct Error
{
int value;
} Error;

static Error const ERROR_OUT_OF_SPACE = { 123 };

pros: type safe. decouple, the error code type is no longer bound with
all the error definition
cons: I don't know any one doing it this way so I'm not sure if it has
some drawbacks or is it bad for (runtime/space) performance.
If using pure C, user could not compare the error value directly but
have to compare the inner "value" member which is not convenience.

Thanks for your help :)

Qiang
Nov 16 '08 #1
Share this Question
Share on Google+
5 Replies


P: n/a
׿ǿ Zhuo wrote:
Hi,

I would like to have someone comments on what's the best practice
defining error codes in C.
Here's what I think:
solution A:
using enum
pros: type safe. better for debug (some debugger will show the name
not only the value)
cons: enum can not be forward declared which makes all error codes
couples together with the error code type ( enum )
By "can not be forward declared," I guess you mean that
you cannot just invent a new error code at some random place
in the program; is that right? If so, I'd say this should be
considered a "pro" and not a "con."
Solution B:
using #define
pros: decouple, error codes could be defined in different .h file
cons: macro is bad. no type safe
"Macro is bad" is bad.
"`Macro is bad' is bad" is bad.
"`«Macro is bad» is bad' is bad" is bad.
...
Solution C:

typedef struct Error
{
int value;
} Error;

static Error const ERROR_OUT_OF_SPACE = { 123 };
Careful! If you include the <errno.hheader -- or if any
code that refers to ERROR_OUT_OF_SPACE includes <errno.h--
Then all identifiers beginning with an E and another upper-case
letter or beginning with E and a digit are reserved.
pros: type safe. decouple, the error code type is no longer bound with
all the error definition
If by "decouple" you mean that it is now possible to invent
new error codes at any random place in the program, I'd say this
should be a "con" rather than a "pro." For one thing, there's
no convenient way to be sure error codes aren't duplicated: what
if somebody defines OUT_OF_CHEESE_ERROR with the value 123?
cons: I don't know any one doing it this way so I'm not sure if it has
some drawbacks or is it bad for (runtime/space) performance.
If using pure C, user could not compare the error value directly but
have to compare the inner "value" member which is not convenience.
Right: Opacity is lost. Also, so is contant-ness, in the
sense that the error objects are not compile-time constants.
You can't use them as `case' labels, for example.

Solutions (A) and (B) are the most common in code I've seen
over the years. I've never seen (C), not in such a bare-bones
form at any rate.

--
Eric Sosman
es*****@ieee-dot-org.invalid
Nov 16 '08 #2

P: n/a
On Sun, 16 Nov 2008 04:48:38 -0800 (PST),
=?GB2312?B?17/HvyBaaHVvLCBRaWFuZw==?= <zh********@gmail.com>
wrote:
>Hi,

I would like to have someone comments on what's the best practice
defining error codes in C.
Here's what I think:
solution A:
using enum
pros: type safe. better for debug (some debugger will show the name
not only the value)
cons: enum can not be forward declared which makes all error codes
couples together with the error code type ( enum )

Solution B:
using #define
pros: decouple, error codes could be defined in different .h file
cons: macro is bad. no type safe

Solution C:

typedef struct Error
{
int value;
} Error;

static Error const ERROR_OUT_OF_SPACE = { 123 };

pros: type safe. decouple, the error code type is no longer bound with
all the error definition
cons: I don't know any one doing it this way so I'm not sure if it has
some drawbacks or is it bad for (runtime/space) performance.
If using pure C, user could not compare the error value directly but
have to compare the inner "value" member which is not convenience.
All choices suffer from the same fundamental flaw; they use error
codes. The advantages of error codes are that they compact and
that they are testable, i.e, if a routine returns an error code
you can take appropriate action based on the error code. These
are advantages in the small.

So, if all you are concerned about is one module, you can use
error code definitions in the modules include file, and it
doesn't much matter whether you use enums or defines - the
decision is a religious one.

Using error codes in a larger scope is not a happy policy. If
you have several people working on a program or collection of
programs you end up with a lot of error codes, and version
control problems. The issue is that the definition of error
codes becomes a version control sensitive bottleneck. There are
various techniques for handling the problem; still you have to
know in advance that there is an issue. Otherwise you eventually
end up with a mess that has to be cleaned up - or lived with.

There is another issue with error codes when programming in the
large; they aren't a solution, they are a tool. Does your big
application have a coherent error management policy? Then error
codes are a detail; if not, then the tail is wagging the dog.

Richard Harter, cr*@tiac.net
http://home.tiac.net/~cri, http://www.varinoma.com
Save the Earth now!!
It's the only planet with chocolate.
Nov 16 '08 #3

P: n/a

"Richard Harter" <cr*@tiac.netwrote in message
There is another issue with error codes when programming in the
large; they aren't a solution, they are a tool. Does your big
application have a coherent error management policy? Then error
codes are a detail; if not, then the tail is wagging the dog.
The real answer is that there is no answer.

What's an error, anyway. Do we mean the machine running out of memory, which
is the only thing that can happen to pure functions, as long as they are
correctly written and called, do we mean internal programmer errors, do we
mean missing resources or bad user input? Does it make sense to handle these
together or separately?

Eg in my program BASICdraw the user will frequently enter a Basic program
with syntax errors in it. However this is to be expected. It can't be
handled in the same way as the machine running out of disk space to store
images.

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm
Nov 16 '08 #4

P: n/a
On 11月16日, 下午9时47分, Eric Sosman <esos...@ieee-dot-org.invalidwrote:
׿ǿ Zhuo wrote:
Hi,
I would like to have someone comments on what's the best practice
defining error codes in C.
Here's what I think:
solution A:
using enum
pros: type safe. better for debug (some debugger will show the name
not only the value)
cons: enum can not be forward declared which makes all error codes
couples together with the error code type ( enum )

* * *By "can not be forward declared," I guess you mean that
you cannot just invent a new error code at some random place
in the program; is that right? *If so, I'd say this should be
considered a "pro" and not a "con."
Yes and No. As a module We'd like to split the error code to two
category, those for the client and those inside. We don't want to
define all the error code in one place which introduce unnecessary
couple. But for one category, it's better that they are defined in one
place.

Solution B:
using #define
pros: decouple, error codes could be defined in different .h file
cons: macro is bad. no type safe

* * *"Macro is bad" is bad.
* * *"`Macro is bad' is bad" is bad.
* * *"`«Macro is bad» is bad' is bad" is bad.
* * *...
So I guess you dislike macro either :)
Solution C:
typedef struct Error
{
int value;
} Error;
static Error const ERROR_OUT_OF_SPACE = { 123 };

* * *Careful! *If you include the <errno.hheader --or if any
code that refers to ERROR_OUT_OF_SPACE includes <errno.h--
Then all identifiers beginning with an E and another upper-case
letter or beginning with E and a digit are reserved.
Thanks for the reminder. Actually all identifiers are prefixed with
module name.(how long will namespace be introduced into C)
pros: type safe. decouple, the error code type is no longer bound with
all the error definition

* * *If by "decouple" you mean that it is now possible to invent
new error codes at any random place in the program, I'd say this
should be a "con" rather than a "pro." *For one thing, there's
no convenient way to be sure error codes aren't duplicated: what
if somebody defines OUT_OF_CHEESE_ERROR with the value 123?
Yes, By decouple I mean the possibility to define new error code
somewhere else. I know it requires discipline to do so. Like I said
we'd like to separate private error code from public interface.
cons: I don't know any one doing it this way so I'm not sure if it has
some drawbacks or is it bad for (runtime/space) performance.
If using pure C, user could not compare the error value directly but
have to compare the inner "value" member which is not convenience.

* * *Right: Opacity is lost. *Also, so is contant-ness, in the
sense that the error objects are not compile-time constants.
You can't use them as `case' labels, for example.
Good point. I guess I have to drop the C) choice

>
* * *Solutions (A) and (B) are the most common in code I've seen
over the years. *I've never seen (C), not in such a bare-bones
form at any rate.
I will stick with solution A) for now.

However, another silly question:

How about:

typedef struct ErrorTag* Error;
static Error const = 123;

I'm living in C++ world, so I want to try my best to make the API type
safe. Is there any way except enum could give a type safe error code
solution ?

Thanks for your time :)
--
Eric Sosman
esos...@ieee-dot-org.invalid
Nov 17 '08 #5

P: n/a
Zhuo wrote:
On 11月16日, 下午9时47分, Eric Sosman <esos...@ieee-dot-org.invalidwrote:
>׿ǿ Zhuo wrote:
>>[...]
using #define
pros: decouple, error codes could be defined in different .h file
cons: macro is bad. no type safe
"Macro is bad" is bad.
"`Macro is bad' is bad" is bad.
"`«Macro is bad» is bad' is bad" is bad.
...
So I guess you dislike macro either :)
No, I mean that unqualified and unsupported out-of-context
statements of the form "X is bad" are bad.
>>Solution C:
typedef struct Error
{
int value;
} Error;
static Error const ERROR_OUT_OF_SPACE = { 123 };
Careful! If you include the <errno.hheader -- or if any
code that refers to ERROR_OUT_OF_SPACE includes <errno.h--
Then all identifiers beginning with an E and another upper-case
letter or beginning with E and a digit are reserved.
Thanks for the reminder. Actually all identifiers are prefixed with
module name.(how long will namespace be introduced into C)
Make sure, then, that you don't name a model EVAPORATE or
EXISTENTIAL or ENNUI or ...

As for the question about name spaces -- well, it's a lot easier
to predict the future after it's happened, right? But my guess is
that name spaces (in the form you probably want them) will never
come to C.
However, another silly question:

How about:

typedef struct ErrorTag* Error;
static Error const = 123;
This is fine -- if you don't mind the diagnostic the compiler
is required to emit and if the compiler accepts the code in spite
of the constraint violation.
I'm living in C++ world, so I want to try my best to make the API type
safe. Is there any way except enum could give a type safe error code
solution ?
I'm not sure why you're so insistent on type safety for error
codes. No doubt type safety beats "type peril" everywhere, but how
important is it here? What kinds of misuse do you fear might befall
your error codes, anyhow?

In any case, C's enum will not provide much type safety. The
named constants are all of type `int', just plain `int', and there's
nothing in the language that prevents them from being used just as
`1' or `42' can be used.

--
Er*********@sun.com
Nov 17 '08 #6

This discussion thread is closed

Replies have been disabled for this discussion.