Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #13778

Re: perror()4 says SUCCESS

From jt@toerring.de (Jens Thoms Toerring)
Newsgroups comp.lang.c
Subject Re: perror()4 says SUCCESS
Date 2011-11-22 11:44 +0000
Organization Freie Universitaet Berlin
Message-ID <9j1g99FufbU1@mid.uni-berlin.de> (permalink)
References <4ecb7bcf$0$292$14726298@news.sunsite.dk>

Show all headers | View raw


arnuld <sunrise@invalid.address> wrote:
> OJECTIVE: Why does perror() says SUCESSS ?

> This code converts a string like "1234" into an unsingned long integer. I 
> wrote it following the discussion here on clc of which I have lost the 
> url from google http interface to newsgroup.


> perror() reports error in else condition many times, I can't understand 
> why:

> int convert_string_to_ulongint(const char* str, unsigned long* ulp)
> {
>   int ret;
>   unsigned long int num;
>   char* p;

>   if(NULL == str || '\0' == *str || NULL == ulp)
>     {
>       printf("IN: %s @ %d: Invalid Args\n", __func__, __LINE__);
>       return VAL_ERR;
>     }

>   p = NULL;
>   errno = 0;
>   num = strtoul(str, &p, 10);

>   /* Error check */
>   if(ERANGE == errno)
>     {
>       if((0 == num) && (0 == strcmp(str, p)))
>         {
>           printf("IN: %s @%d: strtoul() could not perform conversion\n", 
> __func__, __LINE__);
>         }

For this ('num' being 0 and str and p pointing to the same location,
so you could actually use 'str == p' instead of strcmp()) errno
doesn't get set to ERANGE - errno gets set to ERANGE only if there
is a number to convert but it would overflow. Thus if you pass the
function a string that does not start with a number (after possible
white-space) this error isn't caught here but ends up being handled
in the very last 'else'.

>       else if(ULONG_MAX == num)

Everything else than this would mean your libc is broken...

>         {
>           printf("IN: %s @%dp: strtoul() overflow error\n", __func__, 
> __LINE__);
>         }
>       else
>         {
>           printf("IN: %s @%d: strange output from strtoul()\n", __func__, 
> __LINE__);
>         }

>       perror("*ERROR ERANGE*");
>       ret = -1;
>     }
>   else if((0 == errno) && ('\0' == *p))
>     {
>       printf("IN: %s @%d: Successful Conversion by strtoul()\n", 
> __func__, __LINE__);
>       *ulp = num;
>       ret = 1;
>     }
>   else
>     {
>       printf("IN: %s @%d: strange conversions and errno values :(\n", 
> __func__, __LINE__);
>       printf("num = %lu, ULONG_MAX = %lu\n", num, ULONG_MAX);
>       perror("*ERROR in ELSE");

Well, when you get here 'errno' is rather likely 0, and the
reason you're ending up here being that 'str' points to some-
thing that can't be interpreted as a number (or has trailing
parts that aren't a number which you also seem to consider as
being an error). And then perror() can't tell you anything else
than 'SUCCESS' because it interprets the value of 'errno'. So,
unless 'errno' isn't 0 it doesn't make to much sense calling
perror().

>       ret = -1;
>     }

I'd recommend that you change the logic a bit:

a) Check first for 'errno == 0 && *p == '\0''. That shows that
   the conversion was successful.
b) If 'errno' is set to ERANGE report an overflow.
c) Otherwise something must have been wrong about the input
   string: it either couldn't be converted at all (then 'p'
   and 'str' will point to the same location) or there was
   some trailing stuff that couldn't be interpreted as a number
   (in that case you have '*p != '\0').

Another small niggle: Functions shouldn't change errno if they
succeeded. Thus I would recoment to store the original value of
errno before you set errno to 0 and then call strtoul() and reset
errno to its original value if the conversion was successful.

                           Regards, Jens
-- 
  \   Jens Thoms Toerring  ___      jt@toerring.de
   \__________________________      http://toerring.de

Back to comp.lang.c | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread


Thread

perror()4 says SUCCESS arnuld <sunrise@invalid.address> - 2011-11-22 10:39 +0000
  Re: perror()4 says SUCCESS jt@toerring.de (Jens Thoms Toerring) - 2011-11-22 11:44 +0000
  Re: perror()4 says SUCCESS Nick Keighley <nick_keighley_nospam@hotmail.com> - 2011-11-22 04:15 -0800
  Re: perror()4 says SUCCESS Eric Sosman <esosman@ieee-dot-org.invalid> - 2011-11-22 07:51 -0500
  Re: perror()4 says SUCCESS Vincenzo Mercuri <vincenzo.mercuri@yahoo.it> - 2011-11-22 16:51 +0100
    Re: perror()4 says SUCCESS Keith Thompson <kst-u@mib.org> - 2011-11-22 13:30 -0800
      Re: perror()4 says SUCCESS Harald van Dijk <truedfx@gmail.com> - 2011-11-22 13:35 -0800
        Re: perror()4 says SUCCESS Vincenzo Mercuri <vincenzo.mercuri@yahoo.it> - 2011-11-22 22:51 +0100
      Re: perror()4 says SUCCESS James Kuyper <jameskuyper@verizon.net> - 2011-11-22 16:43 -0500
        Re: perror()4 says SUCCESS Ben Pfaff <blp@cs.stanford.edu> - 2011-11-22 15:36 -0800
          Re: perror()4 says SUCCESS James Kuyper <jameskuyper@verizon.net> - 2011-11-22 18:52 -0500
      Re: perror()4 says SUCCESS Vincenzo Mercuri <vincenzo.mercuri@yahoo.it> - 2011-11-22 22:50 +0100
        Re: perror()4 says SUCCESS Keith Thompson <kst-u@mib.org> - 2011-11-22 13:57 -0800
          Re: perror()4 says SUCCESS Vincenzo Mercuri <vincenzo.mercuri@yahoo.it> - 2011-11-22 23:05 +0100
    Re: perror()4 says SUCCESS Vincenzo Mercuri <vincenzo.mercuri@yahoo.it> - 2011-11-22 23:26 +0100
  Re: perror()4 says SUCCESS Eric Sosman <esosman@ieee-dot-org.invalid> - 2011-11-22 20:40 -0500

csiph-web