perror()4 says SUCCESS

Discussion in 'C Programming' started by arnuld, Nov 22, 2011.

  1. arnuld

    arnuld Guest

    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__);
    }
    else if(ULONG_MAX == num)
    {
    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");
    ret = -1;
    }







    --
    arnuld
    http://LispMachine.Wordpress.com
     
    arnuld, Nov 22, 2011
    #1
    1. Advertising

  2. arnuld <> 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 ___
    \__________________________ http://toerring.de
     
    Jens Thoms Toerring, Nov 22, 2011
    #2
    1. Advertising

  3. please include the subject in the body of your post
    Subject: "perror()4 says SUCCESS Options"

    I don't understand what this means
    :)

    On Nov 22, 10:39 am, arnuld <> wrote:

    > OJECTIVE: Why does perror() says SUCESSS ?


    there wasn't an error?

    > 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,


    under what circumstances? I ran a slightly hacked version of your code
    and there was no problem.

    <snip your code>

    <insert my code>
    ******************************************************************
    /* arn.c */

    #include <errno.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stdio.h>

    #define __func__ "convert_string_to_ulongint"
    #define VAL_ERR ERANGE

    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__);
    }
    else if(ULONG_MAX == num)
    {
    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");
    ret = -1;
    }

    return ret;
    }

    int main (void)
    {
    unsigned long result;
    int retval;

    if ((retval = convert_string_to_ulongint("1234", &result)) == 1)
    {
    printf ("conversion succeeded result was %u\n", result);
    return 0;
    }
    else
    {
    printf ("conversion FAILED error flag was %d\n", retval);
    return EXIT_FAILURE;
    }

    return 0;
    }


    ******************************************************************
    </insert my code>

    Output:-

    > arn.exe

    IN: convert_string_to_ulongint @52: Successful Conversion by strtoul()
    conversion succeeded result was 1234
     
    Nick Keighley, Nov 22, 2011
    #3
  4. arnuld

    Eric Sosman Guest

    On 11/22/2011 5:39 AM, arnuld wrote:
    > OJECTIVE: Why does perror() says SUCESSS ?
    >
    > if(ERANGE == errno)
    > {
    >[... eventually call printf() ...]
    > }
    > perror("*ERROR ERANGE*");


    If the penny still hasn't dropped, study this phrase from 7.5p3:
    "The value of errno may be set to nonzero by a library function call
    whether or not there is an error ..."

    --
    Eric Sosman
    d
     
    Eric Sosman, Nov 22, 2011
    #4
  5. Vincenzo Mercuri <> writes:
    > arnuld ha scritto:

    [...]
    >> perror("*ERROR in ELSE");

    > [...]
    >
    > Use printf("Error: %s\n", strerror(err)); instead or the Posix
    > compliant and thread safe "strerror_r()".


    What's the advantage of that over perror()?

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Nov 22, 2011
    #5
  6. On Nov 22, 10:30 pm, Keith Thompson <> wrote:
    > Vincenzo Mercuri <> writes:
    > > arnuld ha scritto:

    > [...]
    > >>        perror("*ERROR in ELSE");

    > > [...]

    >
    > > Use printf("Error: %s\n", strerror(err)); instead or the Posix
    > > compliant and thread safe "strerror_r()".

    >
    > What's the advantage of that over perror()?


    That it prints the error message associated with error code err,
    rather than error code errno. That was the point of the other two
    modifications in the message you replied to: to save the old value of
    errno.
     
    Harald van Dijk, Nov 22, 2011
    #6
  7. arnuld

    James Kuyper Guest

    On 11/22/2011 04:30 PM, Keith Thompson wrote:
    > Vincenzo Mercuri <> writes:
    >> arnuld ha scritto:

    > [...]
    >>> perror("*ERROR in ELSE");

    >> [...]
    >>
    >> Use printf("Error: %s\n", strerror(err)); instead or the Posix
    >> compliant and thread safe "strerror_r()".

    >
    > What's the advantage of that over perror()?


    It goes to stdin rather than stderr; though I'm not sure that counts as
    and advantage; if stderr is different from stdout, I generally want
    messages of this type going to stderr, not stdout. I guess that
    Vincenzo's preferences are different.
     
    James Kuyper, Nov 22, 2011
    #7
  8. Vincenzo Mercuri <> writes:
    > Keith Thompson ha scritto:
    >> Vincenzo Mercuri<> writes:
    >>> arnuld ha scritto:

    >> [...]
    >>>> perror("*ERROR in ELSE");
    >>> [...]
    >>>
    >>> Use printf("Error: %s\n", strerror(err)); instead or the Posix
    >>> compliant and thread safe "strerror_r()".

    >>
    >> What's the advantage of that over perror()?
    >>

    >
    > The point I was making was that while "perror()" prints the string
    > representation of the *current* error described by "errno", with
    > "strerror()" I can print out an error message that refers to a
    > previously stored value of errno, such as "err" in this case.


    Got it, thanks. (I'd still prefer to print the message to stderr rather
    than stdout; that's easy enough to do.)

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Nov 22, 2011
    #8
  9. arnuld

    Ben Pfaff Guest

    James Kuyper <> writes:

    > On 11/22/2011 04:30 PM, Keith Thompson wrote:
    >> Vincenzo Mercuri <> writes:
    >>> arnuld ha scritto:

    >> [...]
    >>>> perror("*ERROR in ELSE");
    >>> [...]
    >>>
    >>> Use printf("Error: %s\n", strerror(err)); instead or the Posix
    >>> compliant and thread safe "strerror_r()".

    >>
    >> What's the advantage of that over perror()?

    >
    > It goes to stdin rather than stderr; [...]


    No.
    --
    Ben Pfaff
    http://benpfaff.org
     
    Ben Pfaff, Nov 22, 2011
    #9
  10. arnuld

    James Kuyper Guest

    On 11/22/2011 06:36 PM, Ben Pfaff wrote:
    > James Kuyper <> writes:
    >
    >> On 11/22/2011 04:30 PM, Keith Thompson wrote:
    >>> Vincenzo Mercuri <> writes:
    >>>> arnuld ha scritto:
    >>> [...]
    >>>>> perror("*ERROR in ELSE");
    >>>> [...]
    >>>>
    >>>> Use printf("Error: %s\n", strerror(err)); instead or the Posix
    >>>> compliant and thread safe "strerror_r()".
    >>>
    >>> What's the advantage of that over perror()?

    >>
    >> It goes to stdin rather than stderr; [...]

    >
    > No.


    Aaagh! Of course I meant stdout, not stdin. Just pretend you didn't see
    that. :-}
     
    James Kuyper, Nov 22, 2011
    #10
  11. arnuld

    Eric Sosman Guest

    On 11/22/2011 5:39 AM, arnuld wrote:
    > OJECTIVE: Why does perror() says SUCESSS ?


    Because it takes elocution lessons from Gollum.

    --
    Eric Sosman
    d
     
    Eric Sosman, Nov 23, 2011
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    0
    Views:
    787
  2. L. Westmeier

    When to use "perror" and "fprintf"

    L. Westmeier, May 4, 2004, in forum: C Programming
    Replies:
    6
    Views:
    773
    OSHIMA
    May 13, 2004
  3. Martin
    Replies:
    7
    Views:
    714
    Chris Torek
    Dec 9, 2004
  4. Clunixchit

    perror question

    Clunixchit, Jun 19, 2005, in forum: C Programming
    Replies:
    1
    Views:
    356
    SM Ryan
    Jun 19, 2005
  5. puzzlecracker

    cout and perror

    puzzlecracker, Oct 22, 2005, in forum: C++
    Replies:
    3
    Views:
    358
    Branimir Maksimovic
    Oct 23, 2005
Loading...

Share This Page