conversion: errno => exception

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Markus Elfring

    conversion: errno => exception

    Do you know a class library that can convert the error/return codes
    that are listed in the standard header file "errno.h" into a
    well-known exception hierarchy?
    Did anybody derive it from "std:runtime_er ror"?

    Regards,
    Markus
  • Alf P. Steinbach

    #2
    Re: conversion: errno => exception

    * Markus Elfring:[color=blue]
    > Do you know a class library that can convert the error/return codes
    > that are listed in the standard header file "errno.h" into a
    > well-known exception hierarchy?
    > Did anybody derive it from "std:runtime_er ror"?[/color]

    Why do you want a hierarchy?

    Off the cuff:

    void throwStdIoError ()
    {
    throw std::runtime_er ror( std::strerror( std::errno ) );
    }


    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?

    Comment

    • Rolf Magnus

      #3
      Re: conversion: errno => exception

      Alf P. Steinbach wrote:
      [color=blue]
      > * Markus Elfring:[color=green]
      >> Do you know a class library that can convert the error/return codes
      >> that are listed in the standard header file "errno.h" into a
      >> well-known exception hierarchy?
      >> Did anybody derive it from "std:runtime_er ror"?[/color]
      >
      > Why do you want a hierarchy?
      >
      > Off the cuff:
      >
      > void throwStdIoError ()
      > {
      > throw std::runtime_er ror( std::strerror( std::errno ) );
      > }[/color]

      It would be quite hard for the function that catches the exception to find
      out what the error actually is.

      Comment

      • Alf P. Steinbach

        #4
        Re: conversion: errno => exception

        * Rolf Magnus:[color=blue]
        > Alf P. Steinbach wrote:
        >[color=green]
        > > * Markus Elfring:[color=darkred]
        > >> Do you know a class library that can convert the error/return codes
        > >> that are listed in the standard header file "errno.h" into a
        > >> well-known exception hierarchy?
        > >> Did anybody derive it from "std:runtime_er ror"?[/color]
        > >
        > > Why do you want a hierarchy?
        > >
        > > Off the cuff:
        > >
        > > void throwStdIoError ()
        > > {
        > > throw std::runtime_er ror( std::strerror( std::errno ) );
        > > }[/color]
        >
        > It would be quite hard for the function that catches the exception to find
        > out what the error actually is.[/color]

        If it's not within the context of the throwing call, why should it care?

        --
        A: Because it messes up the order in which people normally read text.
        Q: Why is it such a bad thing?
        A: Top-posting.
        Q: What is the most annoying thing on usenet and in e-mail?

        Comment

        • Markus Elfring

          #5
          Re: conversion: errno => exception

          > Why do you want a hierarchy?

          The reasons are similar to the design decisions for the base classes
          that are specified in the header <exception> and related files.
          I would like to unify error reporting and put return codes into groups
          or categories. I see a problem there to find the appropriate names for
          the categorization.

          The application of design patterns is another use case.
          - http://www.refactoring.com/catalog/r...ymorphism.html
          - http://www.refactoring.com/catalog/r...WithClass.html
          - http://industriallogic.com/xp/refact...WithClass.html

          I imagine a factory class that provides a method like this one.
          errno_exception & create(int err_no) const throw(std::out_ of_range);

          I suggest two approaches for its implementation.
          1. a huge switch statement
          2. Instances are copied from a static collection (array, vector or
          map).

          Have you got more ideas?
          Is a complete solution available already?

          Regards,
          Markus

          Comment

          • Alf P. Steinbach

            #6
            Re: conversion: errno =&gt; exception

            * Markus Elfring:[color=blue][color=green]
            > > Why do you want a hierarchy?[/color]
            >
            > The reasons are similar to the design decisions for the base classes
            > that are specified in the header <exception> and related files.
            > I would like to unify error reporting and put return codes into groups
            > or categories. I see a problem there to find the appropriate names for
            > the categorization.[/color]

            If naming is a problem, then the idea is probably not meaningful.

            The base classes in <exception> are meant to facilitate different handling
            of different kinds of error state, primarily to diffentiate between
            recoverable/ignorable on the one hand, and unrecoverable/non-ignorable.

            But <exception> is very badly designed (if it is designed at all ;-)).
            It probably emerged as a "let's get it over with, choose something!" solution
            to a lot of confusion and disagreement. And so for many years Microsoft's
            documentation incorrectly referred to a completely different hierarchy...

            [color=blue]
            > The application of design patterns is another use case.
            > - http://www.refactoring.com/catalog/r...ymorphism.html
            > - http://www.refactoring.com/catalog/r...WithClass.html
            > - http://industriallogic.com/xp/refact...WithClass.html[/color]

            Regarding "replaceTypeCod eWithClass", consider how much easier it is to
            "replace type code with log message", which is all you ordinarily need.

            Do not be blinded by design patterns.

            A list of design patterns can be a good source of ideas, but forcing a
            pattern on a design is usually UnGood: instead, see what pattern is there
            in the first place.

            [color=blue]
            > I imagine a factory class that provides a method like this one.
            > errno_exception & create(int err_no) const throw(std::out_ of_range);[/color]

            Regarding C++ the result should be const, and it's not a good idea to use
            std::out_of_ran ge (I haven't checked that the name is correct): instead,
            use std::runtime_er ror or derived classes for recoverable errors, so that
            other code won't get an exception it doesn't expect and won't have to
            check for a zillion silly different types of exception.

            --
            A: Because it messes up the order in which people normally read text.
            Q: Why is it such a bad thing?
            A: Top-posting.
            Q: What is the most annoying thing on usenet and in e-mail?

            Comment

            • Rolf Magnus

              #7
              Re: conversion: errno =&gt; exception

              Alf P. Steinbach wrote:
              [color=blue]
              > * Rolf Magnus:[color=green]
              >> Alf P. Steinbach wrote:
              >>[color=darkred]
              >> > * Markus Elfring:
              >> >> Do you know a class library that can convert the error/return codes
              >> >> that are listed in the standard header file "errno.h" into a
              >> >> well-known exception hierarchy?
              >> >> Did anybody derive it from "std:runtime_er ror"?
              >> >
              >> > Why do you want a hierarchy?
              >> >
              >> > Off the cuff:
              >> >
              >> > void throwStdIoError ()
              >> > {
              >> > throw std::runtime_er ror( std::strerror( std::errno ) );
              >> > }[/color]
              >>
              >> It would be quite hard for the function that catches the exception to
              >> find out what the error actually is.[/color]
              >
              > If it's not within the context of the throwing call, why should it care?[/color]

              If it doesn't care, what's the purpose of the exception?


              Comment

              • Alf P. Steinbach

                #8
                Re: conversion: errno =&gt; exception

                * Rolf Magnus:[color=blue]
                > Alf P. Steinbach wrote:
                >[color=green]
                > > * Rolf Magnus:[color=darkred]
                > >> Alf P. Steinbach wrote:
                > >>
                > >> > * Markus Elfring:
                > >> >> Do you know a class library that can convert the error/return codes
                > >> >> that are listed in the standard header file "errno.h" into a
                > >> >> well-known exception hierarchy?
                > >> >> Did anybody derive it from "std:runtime_er ror"?
                > >> >
                > >> > Why do you want a hierarchy?
                > >> >
                > >> > Off the cuff:
                > >> >
                > >> > void throwStdIoError ()
                > >> > {
                > >> > throw std::runtime_er ror( std::strerror( std::errno ) );
                > >> > }
                > >>
                > >> It would be quite hard for the function that catches the exception to
                > >> find out what the error actually is.[/color]
                > >
                > > If it's not within the context of the throwing call, why should it care?[/color]
                >
                > If it doesn't care, what's the purpose of the exception?[/color]

                Most actual code does not use information about the type of a caught
                exception.

                The only relevant information is, usually, that an exception occurred, and
                (for purposes of logging) the explanatory string carried by the exception.

                Hence your question is really "why does C++ support exceptions", and that
                belongs in [comp.std.c++], or a programming textbook, if anywhere.

                --
                A: Because it messes up the order in which people normally read text.
                Q: Why is it such a bad thing?
                A: Top-posting.
                Q: What is the most annoying thing on usenet and in e-mail?

                Comment

                • Tom Widmer

                  #9
                  Re: conversion: errno =&gt; exception

                  On 8 Nov 2004 10:59:11 -0800, Markus.Elfring@ web.de (Markus Elfring)
                  wrote:
                  [color=blue][color=green]
                  >> Why do you want a hierarchy?[/color]
                  >
                  >The reasons are similar to the design decisions for the base classes
                  >that are specified in the header <exception> and related files.
                  >I would like to unify error reporting and put return codes into groups
                  >or categories. I see a problem there to find the appropriate names for
                  >the categorization.
                  >
                  >The application of design patterns is another use case.
                  >- http://www.refactoring.com/catalog/r...ymorphism.html
                  >- http://www.refactoring.com/catalog/r...WithClass.html
                  >- http://industriallogic.com/xp/refact...WithClass.html
                  >
                  >I imagine a factory class that provides a method like this one.
                  > errno_exception & create(int err_no) const throw(std::out_ of_range);[/color]

                  That isn't going to work, since if you do:

                  throw create(errno);

                  the exception object will be sliced, since in C++ the static type of a
                  throw statement determines the type of exception thrown. This of
                  course assumes that you are going to add classes derived from
                  errno_exception .
                  [color=blue]
                  >I suggest two approaches for its implementation.
                  >1. a huge switch statement
                  >2. Instances are copied from a static collection (array, vector or
                  >map).
                  >
                  >Have you got more ideas?[/color]

                  You could use a map from error number to a throw function. e.g.

                  template <class Exception> void thrower(int errorCode/*other
                  params?*/)
                  {
                  throw Exception(error Code/*other params?*/);
                  }

                  and a map:

                  std::map<int, void(int)> throwers;

                  Insert in the map with:

                  throwers[someErrorCode] = &thrower<SomeEx ceptionClass>;

                  Then you throw with:

                  void throwErrNo(int errorNumber/*other params?*/)
                  {
                  iterator i = throwers.find(s omeErrorCode);
                  if (i != throwers.end())
                  {
                  (i->second)(someEr rorCode/*other params?*/);
                  }
                  else
                  {
                  //either throw errno_exception or out_of_range
                  //or even assert?
                  }
                  }

                  If the sequence of error numbers is fairly contiguous, you could use a
                  vector rather than a map. Alternatively, you could just use the switch
                  statement - this depends on whether you want the thing to be runtime
                  pluggable with new error codes, etc.
                  [color=blue]
                  >Is a complete solution available already?[/color]

                  Not that I know of.

                  Tom

                  Comment

                  • Alf P. Steinbach

                    #10
                    Re: conversion: errno =&gt; exception

                    * Tom Widmer:[color=blue]
                    > * Markus Elfring:[color=green]
                    > >
                    > >I imagine a factory class that provides a method like this one.
                    > > errno_exception & create(int err_no) const throw(std::out_ of_range);[/color]
                    >
                    > That isn't going to work, since if you do:
                    >
                    > throw create(errno);
                    >
                    > the exception object will be sliced, since in C++ the static type of a
                    > throw statement determines the type of exception thrown. This of
                    > course assumes that you are going to add classes derived from
                    > errno_exception .[/color]

                    Well, what you describe here wasn't mentioned by Markus.

                    Hence the "that" that isn't going to work is your code... ;-)

                    Because of that the natural assumption is that his errno_exception is a
                    factory, or that it directly provides a virtual throw function.

                    --
                    A: Because it messes up the order in which people normally read text.
                    Q: Why is it such a bad thing?
                    A: Top-posting.
                    Q: What is the most annoying thing on usenet and in e-mail?

                    Comment

                    • Tom Widmer

                      #11
                      Re: conversion: errno =&gt; exception

                      On Tue, 09 Nov 2004 22:29:24 GMT, alfps@start.no (Alf P. Steinbach)
                      wrote:
                      [color=blue]
                      >* Tom Widmer:[color=green]
                      >> * Markus Elfring:[color=darkred]
                      >> >
                      >> >I imagine a factory class that provides a method like this one.
                      >> > errno_exception & create(int err_no) const throw(std::out_ of_range);[/color]
                      >>
                      >> That isn't going to work, since if you do:
                      >>
                      >> throw create(errno);
                      >>
                      >> the exception object will be sliced, since in C++ the static type of a
                      >> throw statement determines the type of exception thrown. This of
                      >> course assumes that you are going to add classes derived from
                      >> errno_exception .[/color]
                      >
                      >Well, what you describe here wasn't mentioned by Markus.
                      >
                      >Hence the "that" that isn't going to work is your code... ;-)
                      >
                      >Because of that the natural assumption is that his errno_exception is a
                      >factory, or that it directly provides a virtual throw function.[/color]

                      True, but I thought it was worth highlighting the issue just in case
                      he wasn't aware of it.

                      Actually, a virtual throw method is generally a good idea in any
                      exception heirarchy, along with a clone method, so that you can
                      propogate exceptions between threads, etc.

                      Tom

                      Comment

                      • Markus Elfring

                        #12
                        Re: conversion: errno =&gt; exception

                        > That isn't going to work, since if you do:

                        How do you think about an interface like this one?
                        virtual errno_exception & create(int err_no) const;

                        [color=blue]
                        > throw create(errno);[/color]

                        I would like to use ...
                        throw my_exception_fa ctory.create(er rno);

                        [color=blue]
                        > the exception object will be sliced, since in C++ the static type of a
                        > throw statement determines the type of exception thrown. This of
                        > course assumes that you are going to add classes derived from
                        > errno_exception .[/color]

                        I do not think that "object slicing" will happen.


                        How does your statement fit to the handling of "covariant return types"?



                        Comment

                        • Tom Widmer

                          #13
                          Re: conversion: errno =&gt; exception

                          On 12 Nov 2004 03:14:26 -0800, Markus.Elfring@ web.de (Markus Elfring)
                          wrote:
                          [color=blue][color=green]
                          >> That isn't going to work, since if you do:[/color]
                          >
                          >How do you think about an interface like this one?
                          > virtual errno_exception & create(int err_no) const;
                          >
                          >[color=green]
                          >> throw create(errno);[/color]
                          >
                          >I would like to use ...
                          > throw my_exception_fa ctory.create(er rno);[/color]

                          That's exactly what won't work. You will need something like:

                          my_exception_fa ctory.create(er rno).throw_self ();

                          where throw_self is a virtual function that is implemented in every
                          exception class that simply does throw *this;
                          Or you can have:

                          my_exception_fa ctory.throw_err or(errno);

                          or similar.
                          [color=blue][color=green]
                          >> the exception object will be sliced, since in C++ the static type of a
                          >> throw statement determines the type of exception thrown. This of
                          >> course assumes that you are going to add classes derived from
                          >> errno_exception .[/color]
                          >
                          >I do not think that "object slicing" will happen.
                          >http://www.savinov.spb.ru/think/tic0161.html#Heading428[/color]

                          Throwing an exception involves copying it. In the statement "throw t"
                          the static type of t is used to determine the exception that is
                          thrown. t is copied into a "temporary" exception object of type
                          static-type-of-t, and this copy will be a slice if the static type of
                          t doesn't match its dynamic type.
                          [color=blue]
                          >How does your statement fit to the handling of "covariant return types"?
                          >http://www.fmi.uni-konstanz.de/~kueh....html#faq-20.6
                          >http://www.fmi.uni-konstanz.de/~kueh....html#faq-22.5
                          >http://semantics.org/once_weakly/ck1...iantreturn.pdf[/color]

                          I don't think that covariant returns will make any difference here.

                          Tom

                          Comment

                          • Markus Elfring

                            #14
                            Re: conversion: errno =&gt; exception

                            > Throwing an exception involves copying it. In the statement "throw t"[color=blue]
                            > the static type of t is used to determine the exception that is
                            > thrown. t is copied into a "temporary" exception object of type
                            > static-type-of-t, and this copy will be a slice if the static type of
                            > t doesn't match its dynamic type.[/color]

                            How do you think about the effects by the following design sketch?

                            #include <iostream.h>
                            #include <errno.h>

                            struct errno_exception
                            {
                            virtual ~errno_exceptio n() {}
                            virtual int get_code() const { return EZERO; }
                            };


                            struct invalid : public errno_exception
                            {
                            };


                            struct invalid_value : public invalid
                            {
                            virtual int get_code() const { return EINVAL; }
                            };


                            struct invalid_environ ment : public invalid
                            {
                            virtual int get_code() const { return EINVENV; }
                            };


                            struct invalid_format : public invalid
                            {
                            virtual int get_code() const { return EINVFMT; }
                            };


                            struct no_entry : public errno_exception
                            {
                            virtual int get_code() const { return ENOENT; }
                            };


                            struct exception_facto ry
                            {
                            virtual ~exception_fact ory() {}
                            virtual errno_exception & create (int err_no) const = 0;
                            };


                            struct factory1 : public exception_facto ry
                            {
                            virtual errno_exception & create (int err_no) const;
                            };


                            struct errno_exception s
                            {
                            errno_exception _ZERO;
                            no_entry _NOENT;
                            invalid_format _INVFMT;
                            invalid_environ ment _INVENV;
                            invalid_value _INVAL;
                            };


                            errno_exception s my_e_e;


                            errno_exception & factory1::creat e (int err_no) const
                            {
                            switch (err_no)
                            {
                            case ENOENT:
                            return my_e_e._NOENT;

                            case EINVFMT:
                            return my_e_e._INVFMT;

                            case EINVENV:
                            return my_e_e._INVENV;

                            case EINVAL:
                            return my_e_e._INVAL;

                            default:
                            return my_e_e._ZERO;
                            }
                            }


                            struct exception_throw er
                            {
                            virtual ~exception_thro wer() {}
                            virtual void create (int code) const = 0;
                            };


                            struct factory2 : public exception_throw er
                            {
                            virtual void create (int code) const;
                            };


                            void factory2::creat e (int code) const
                            {
                            switch (code)
                            {
                            case ENOENT:
                            throw no_entry();

                            case EINVFMT:
                            throw invalid_format( );

                            case EINVENV:
                            throw invalid_environ ment();

                            case EINVAL:
                            throw invalid_value() ;

                            default:
                            throw errno_exception ();
                            }
                            }


                            int main ()
                            {
                            factory1 f1;

                            try
                            {
                            throw f1.create(EINVF MT);
                            }
                            catch (invalid const& i)
                            {
                            cout << "1. invalid = " << i.get_code() << endl;
                            }
                            catch (errno_exceptio n const& e)
                            {
                            cout << "1. errno exception base" << endl;
                            }

                            try
                            {
                            factory2 f2;
                            f2.create(EINVF MT);
                            }
                            catch (invalid const& i)
                            {
                            cout << "2. invalid = " << i.get_code() << endl;
                            }
                            catch (errno_exceptio n const& e)
                            {
                            cout << "2. errno exception base" << endl;
                            }

                            return 0;
                            }



                            Comment

                            Working...