What's The Best Practice Defining Error Codes in C

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • =?GB2312?B?17/HvyBaaHVvLCBRaWFuZw==?=

    What's The Best Practice Defining Error Codes in C

    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_SP ACE = { 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
  • Eric Sosman

    #2
    Re: What's The Best Practice Defining Error Codes in C

    ׿ǿ 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_SP ACE = { 123 };
    Careful! If you include the <errno.hheade r -- or if any
    code that refers to ERROR_OUT_OF_SP ACE 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_E RROR 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
    esosman@ieee-dot-org.invalid

    Comment

    • Richard Harter

      #3
      Re: What's The Best Practice Defining Error Codes in C

      On Sun, 16 Nov 2008 04:48:38 -0800 (PST),
      =?GB2312?B?17/HvyBaaHVvLCBRaW FuZw==?= <zhuo.qiang@gma il.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_SP ACE = { 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, cri@tiac.net
      http://home.tiac.net/~cri, http://www.varinoma.com
      Save the Earth now!!
      It's the only planet with chocolate.

      Comment

      • Malcolm McLean

        #4
        Re: What's The Best Practice Defining Error Codes in C


        "Richard Harter" <cri@tiac.netwr ote 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.



        Comment

        • =?GB2312?B?Wmh1bywgUWlhbmcg17/Hvw==?=

          #5
          Re: What's The Best Practice Defining Error Codes in C

          On 11月16日, 下午9时47分 , Eric Sosman <esos...@ieee-dot-org.invalidwrot e:
          ׿ǿ 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_SP ACE = { 123 };
          >
               Careful!  If you include the <errno.hheade r --or if any
          code that refers to ERROR_OUT_OF_SP ACE 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_E RROR 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

          Comment

          • Eric Sosman

            #6
            Re: What's The Best Practice Defining Error Codes in C

            Zhuo wrote:
            On 11月16日, 下午9时47分 , Eric Sosman <esos...@ieee-dot-org.invalidwrot e:
            >׿ǿ 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_SP ACE = { 123 };
            > Careful! If you include the <errno.hheade r -- or if any
            >code that refers to ERROR_OUT_OF_SP ACE 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.

            --
            Eric.Sosman@sun .com

            Comment

            Working...