How to handle invalid argument with C?

Discussion in 'C Programming' started by Lambda, Nov 6, 2007.

  1. Lambda

    Lambda Guest

    When I call the standard strncpy function, I provide it a negative
    argument,
    such as:

    strncpy(s, ct, -1)

    I compile the code with gcc, when I run, it says "Segmentation fault".
    Do you think it's ok? I try this to see how the library handle invalid
    parameter.

    When I define my own function, should I handle this kind of argument?
    And if so, how can I tell the caller the argument is wrong?
    Return some error code such as -1?
    But how about the function return type is void?

    I know in Java, I can define some invalid parameter exception to
    indicate this.
    What can I do with C?
    Lambda, Nov 6, 2007
    #1
    1. Advertising

  2. Lambda

    Ian Collins Guest

    Lambda wrote:
    > When I call the standard strncpy function, I provide it a negative
    > argument,
    > such as:
    >
    > strncpy(s, ct, -1)
    >
    > I compile the code with gcc, when I run, it says "Segmentation fault".
    > Do you think it's ok? I try this to see how the library handle invalid
    > parameter.
    >

    The third parameter to strncpy is size_t which is unsigned. (size_t)-1
    is a very big number.

    > When I define my own function, should I handle this kind of argument?
    > And if so, how can I tell the caller the argument is wrong?
    > Return some error code such as -1?
    > But how about the function return type is void?
    >

    The the function can return an error, don't use void as the return type.

    > I know in Java, I can define some invalid parameter exception to
    > indicate this.
    > What can I do with C?
    >

    Return an error, if you can tell the parameter is invalid.

    --
    Ian Collins.
    Ian Collins, Nov 6, 2007
    #2
    1. Advertising

  3. Lambda

    santosh Guest

    On Tuesday 06 Nov 2007 1:26 pm Lambda <> wrote in
    article <>:

    > When I call the standard strncpy function, I provide it a negative
    > argument,
    > such as:
    >
    > strncpy(s, ct, -1)


    Here -1 is converted to the type size_t which is an unsigned integer.
    Thus this actually results in strncpy receiving a very large positive
    value. The segmentation fault is probably caused by strncpy trying to
    read memory far beyond the legal limits.

    > I compile the code with gcc, when I run, it says "Segmentation fault".
    > Do you think it's ok? I try this to see how the library handle invalid
    > parameter.


    In C each function is documented clearly as to what type of values it
    accepts. In addition to this there are situations where many values do
    not make any sense.

    In general the programmer has to be careful to pass the correct type and
    range of values to the Standard library function.

    > When I define my own function, should I handle this kind of argument?


    It's a matter of trade-off. It's very common nowadays to sacrifice a
    minuscule amount of runtime efficiency to check for common exceptions
    like invalid arguments.

    Nevertheless there are many situations where such checks are either
    inappropriate or not possible, not least of which is the situation
    where the callee has no idea if an argument is a valid value. Such
    information belongs to the caller. Library function generally blindly
    accept the arguments that they are given barring a few elementary check
    like null pointer values, checking for values outside the accepted
    domain etc.

    > And if so, how can I tell the caller the argument is wrong?


    By setting some kind of error indicator. I generally return a status
    value where this is convenient. Otherwise I treat one of the arguments
    as a pointer to an object which receives the status value. I usually
    don't use global objects like errno.

    > Return some error code such as -1?


    Yes. However designing proper error codes is not a trivial task and
    changing things retrospectively is often difficult. Also use symbolic
    constants instead of literals.

    > But how about the function return type is void?


    Then the function either has to set an external object, or access an
    object through one of it's arguments or invoke a callback function, or
    raise a signal or...

    Clearly there are numerous ways. Which one is appropriate for a given
    function is very dependent on the function's details and related
    context.

    > I know in Java, I can define some invalid parameter exception to
    > indicate this.
    > What can I do with C?


    C doesn't have standardised support for exceptions so unless your
    willing to simulate them, the usual method is to rely on explicit
    checking of status values each time the function is invoked. Wrappers
    can encapsulate and abstract these details to a large extent.
    santosh, Nov 6, 2007
    #3
  4. Lambda

    Lambda Guest

    On Nov 6, 4:12 pm, Ian Collins <> wrote:
    > Lambda wrote:
    > > When I call the standard strncpy function, I provide it a negative
    > > argument,
    > > such as:

    >
    > > strncpy(s, ct, -1)

    >
    > > I compile the code with gcc, when I run, it says "Segmentation fault".
    > > Do you think it's ok? I try this to see how the library handle invalid
    > > parameter.

    >
    > The third parameter to strncpy is size_t which is unsigned. (size_t)-1
    > is a very big number.
    >
    > > When I define my own function, should I handle this kind of argument?
    > > And if so, how can I tell the caller the argument is wrong?
    > > Return some error code such as -1?
    > > But how about the function return type is void?

    >
    > The the function can return an error, don't use void as the return type.
    >
    > > I know in Java, I can define some invalid parameter exception to
    > > indicate this.
    > > What can I do with C?

    >
    > Return an error, if you can tell the parameter is invalid.


    Ian, thank you for your reply.
    Maybe this is the only solution with C.

    The problem is an error code does not indicate what problem it is.
    I can not return some text to indicate the problem,
    for example 'the n argument must be a valid array index, >= 0 and <
    size'
    I have to write all these in the function document and wish the user
    note them.

    Another problem is some error code such as -1 can be a legal return
    value.
    I must try to find good error code.

    Exception in C++ and Java is a elegant solution, i think.

    > --
    > Ian Collins.
    Lambda, Nov 6, 2007
    #4
  5. Lambda

    Ian Collins Guest

    Lambda wrote:
    > On Nov 6, 4:12 pm, Ian Collins <> wrote:
    >> Lambda wrote:
    >>> When I call the standard strncpy function, I provide it a negative
    >>> argument,
    >>> such as:
    >>> strncpy(s, ct, -1)
    >>> I compile the code with gcc, when I run, it says "Segmentation fault".
    >>> Do you think it's ok? I try this to see how the library handle invalid
    >>> parameter.

    >> The third parameter to strncpy is size_t which is unsigned. (size_t)-1
    >> is a very big number.
    >>
    >>> When I define my own function, should I handle this kind of argument?
    >>> And if so, how can I tell the caller the argument is wrong?
    >>> Return some error code such as -1?
    >>> But how about the function return type is void?

    >> The the function can return an error, don't use void as the return type.
    >>
    >>> I know in Java, I can define some invalid parameter exception to
    >>> indicate this.
    >>> What can I do with C?

    >> Return an error, if you can tell the parameter is invalid.

    >
    > Ian, thank you for your reply.
    > Maybe this is the only solution with C.
    >
    > The problem is an error code does not indicate what problem it is.
    > I can not return some text to indicate the problem,
    > for example 'the n argument must be a valid array index, >= 0 and <
    > size'
    > I have to write all these in the function document and wish the user
    > note them.
    >

    Error codes work fine, or returning -1 and setting errno which is
    typical of system calls. Some environments define an enum of error
    codes and have all their system calls return a value of that type.

    --
    Ian Collins.
    Ian Collins, Nov 6, 2007
    #5
  6. Lambda

    Richard Guest

    Lambda <> writes:

    > On Nov 6, 4:12 pm, Ian Collins <> wrote:
    >> Lambda wrote:
    >> > When I call the standard strncpy function, I provide it a negative
    >> > argument,
    >> > such as:

    >>
    >> > strncpy(s, ct, -1)

    >>
    >> > I compile the code with gcc, when I run, it says "Segmentation fault".
    >> > Do you think it's ok? I try this to see how the library handle invalid
    >> > parameter.

    >>
    >> The third parameter to strncpy is size_t which is unsigned. (size_t)-1
    >> is a very big number.
    >>
    >> > When I define my own function, should I handle this kind of argument?
    >> > And if so, how can I tell the caller the argument is wrong?
    >> > Return some error code such as -1?
    >> > But how about the function return type is void?

    >>
    >> The the function can return an error, don't use void as the return type.
    >>
    >> > I know in Java, I can define some invalid parameter exception to
    >> > indicate this.
    >> > What can I do with C?

    >>
    >> Return an error, if you can tell the parameter is invalid.

    >
    > Ian, thank you for your reply.
    > Maybe this is the only solution with C.
    >
    > The problem is an error code does not indicate what problem it is.


    That is exactly what it does. This error code is documented according to
    its values

    e.g

    -2 : null pointer

    or whatever you choose.

    It is generally better to return 0 for success IMO.


    > I can not return some text to indicate the problem,
    > for example 'the n argument must be a valid array index, >= 0 and <
    > size'
    > I have to write all these in the function document and wish the user
    > note them.


    Yes. Or you could also have a log function which converts the code into
    descriptive text.

    >
    > Another problem is some error code such as -1 can be a legal return
    > value.
    > I must try to find good error code.


    There is only success or one of many errors from what I can see. What do
    you mean by -1 can be a legal return? Are you rewriting strncpy or are
    you talking more generally?

    >
    > Exception in C++ and Java is a elegant solution, i think.
    >
    >> --
    >> Ian Collins.
    Richard, Nov 6, 2007
    #6
  7. In article <>,
    Richard <> wrote:

    >>> > strncpy(s, ct, -1)


    [...]

    >That is exactly what it does. This error code is documented according to
    >its values
    >
    >e.g
    >
    >-2 : null pointer


    I don't think this is very useful in a case like strncpy. A null
    string or bogus length almost certainly indicate a program error
    (rather than a data error), and putting in code to check your code for
    errors is of limited use. If there's something wrong with your
    program, how often can you recover? Why didn't you check the values
    when they were calculated, instead of waiting until they were passed
    to a library function? Would you really test the return value of
    every str* function you called and do something sensible?

    -- Richard
    --
    "Consideration shall be given to the need for as many as 32 characters
    in some alphabets" - X3.4, 1963.
    Richard Tobin, Nov 6, 2007
    #7
  8. Lambda

    santosh Guest

    On Tuesday 06 Nov 2007 2:05 pm Lambda <> wrote in
    article <>:

    > On Nov 6, 4:12 pm, Ian Collins <> wrote:
    >> Lambda wrote:
    >> > When I call the standard strncpy function, I provide it a negative
    >> > argument,
    >> > such as:

    >>
    >> > strncpy(s, ct, -1)

    >>
    >> > I compile the code with gcc, when I run, it says "Segmentation
    >> > fault". Do you think it's ok? I try this to see how the library
    >> > handle invalid parameter.

    >>
    >> The third parameter to strncpy is size_t which is unsigned.
    >> (size_t)-1 is a very big number.
    >>
    >> > When I define my own function, should I handle this kind of
    >> > argument? And if so, how can I tell the caller the argument is
    >> > wrong? Return some error code such as -1?
    >> > But how about the function return type is void?

    >>
    >> The the function can return an error, don't use void as the return
    >> type.
    >>
    >> > I know in Java, I can define some invalid parameter exception to
    >> > indicate this.
    >> > What can I do with C?

    >>
    >> Return an error, if you can tell the parameter is invalid.

    >
    > Ian, thank you for your reply.
    > Maybe this is the only solution with C.
    >
    > The problem is an error code does not indicate what problem it is.
    > I can not return some text to indicate the problem,
    > for example 'the n argument must be a valid array index, >= 0 and <
    > size'


    Of course this can be, though it may be considerable work. You can write
    dedicated "converting" function that takes an error code and produces
    the appropriate error message. Then a logging function can display this
    howsoever it wishes.

    Again the tricky thing is the design. Hitting upon an elegant, efficient
    yet flexible design is not trivial. Once you have the detailed
    blueprint, writing the code is relatively straightforward.

    Once again C gives you the freedom to design this in many ways. The
    selection has to be made by the programmer. A good book on general
    software engineering like _Code Complete_ might be a good help in this
    regard.

    > I have to write all these in the function document and wish the user
    > note them.


    This is also essential for any serious code.

    > Another problem is some error code such as -1 can be a legal return
    > value.


    In this case I separate the return value and the error value and return
    both by separate channels.

    > Exception in C++ and Java is a elegant solution, i think.


    They have their problems too.
    santosh, Nov 6, 2007
    #8
  9. Lambda

    Marc Boyer Guest

    On 2007-11-06, Lambda <> wrote:
    > When I call the standard strncpy function, I provide it a negative
    > argument,
    > such as:
    >
    > strncpy(s, ct, -1)
    >
    > I compile the code with gcc, when I run, it says "Segmentation fault".
    > Do you think it's ok? I try this to see how the library handle invalid
    > parameter.


    First of all, from the strncpy function, there is no invalid
    parameter. The '-1' is implicity converted into (size_t)-1, a
    huge positive value.

    > When I define my own function, should I handle this kind of argument?
    > And if so, how can I tell the caller the argument is wrong?
    > Return some error code such as -1?
    > But how about the function return type is void?
    >
    > I know in Java, I can define some invalid parameter exception to
    > indicate this.


    But you also have to change the signature
    void strncpy( ... ) throw InvalidParamter;

    > What can I do with C?


    Error handling is a common pb in software...
    There are several problems and strategies, and there are several kinds
    of errors.

    I personnaly makes a difference between 'external errors'
    (malloc, fopen, strtoul failure) and 'programming error' (passing
    a NULL pointer to strncpy).

    There also have different strategies:
    - return code
    - global error code (like errno)
    - loging and assert-like mechanisms
    - exceptions

    The questions are:
    - where/how did you detect the error
    - where/how did you signal the error
    - where/how did you handle the error
    and also
    - how did you document the conditions


    In C, return code and global error code are the most common tools
    for external errors. There are more debates about assert. The same,
    some consider setjmp / longjmp as a low-level exceptions mechanisms
    (see http://ldeniau.web.cern.ch/ldeniau/oopc.html for example).

    Personnaly, I consider that external errors should be handled with
    return code (with the help of global error code) and assert-like for
    programming errors. I have no strong opinion about setjmp/longjmp.

    Marc Boyer
    Marc Boyer, Nov 6, 2007
    #9
  10. Lambda

    Chris Dollin Guest

    Marc Boyer wrote:

    > On 2007-11-06, Lambda <> wrote:


    >> I know in Java, I can define some invalid parameter exception to
    >> indicate this.

    >
    > But you also have to change the signature
    > void strncpy( ... ) throw InvalidParamter;


    (fx:OT) Not if InvalidParameter is a subclass of RuntimeException.

    --
    Chris "as JenaException is" Dollin

    Hewlett-Packard Limited Cain Road, Bracknell, registered no:
    registered office: Berks RG12 1HN 690597 England
    Chris Dollin, Nov 6, 2007
    #10
  11. Lambda

    Marc Boyer Guest

    On 2007-11-06, Chris Dollin <> wrote:
    > Marc Boyer wrote:
    >> On 2007-11-06, Lambda <> wrote:

    >
    >>> I know in Java, I can define some invalid parameter exception to
    >>> indicate this.

    >>
    >> But you also have to change the signature
    >> void strncpy( ... ) throw InvalidParamter;

    >
    > (fx:OT) Not if InvalidParameter is a subclass of RuntimeException.


    Yes. As in C with void*, you can switch the type-checking system
    off.


    Marc Boyer
    Marc Boyer, Nov 6, 2007
    #11
  12. Lambda

    Tor Rustad Guest

    Lambda wrote:
    > When I call the standard strncpy function, I provide it a negative
    > argument,
    > such as:
    >
    > strncpy(s, ct, -1)
    >
    > I compile the code with gcc, when I run, it says "Segmentation fault".
    > Do you think it's ok? I try this to see how the library handle invalid
    > parameter.


    It's not ok.
    It's not ok.
    It's not ok....never do buffer overflow C!

    It's a meaningless test, you invoke UB when you read outside the range
    of the 'ct' object, you invoke UB when you update outside the range of
    the 's' object.

    Note, (size_t) -1 wraps around, and is the maximum value an object of
    type size_t can have.

    > When I define my own function, should I handle this kind of argument?


    To avoid GIGO, we normally check the function parameters, validating
    they are within allowed range.

    You decide on your own, if these checks should be done run-time or only
    in debug builds.

    > And if so, how can I tell the caller the argument is wrong?


    A number of alternatives exists e.g.

    1. assert() for program faults
    2. return an error code
    3. invoke your home build error function
    4. terminate the program via exit() call
    5. longjmp() - not recommended for beginners

    > Return some error code such as -1?



    > But how about the function return type is void?


    void foo(int *error)

    or

    void foo(struct *param)

    comes to mind.

    > I know in Java, I can define some invalid parameter exception to
    > indicate this.
    > What can I do with C?


    Welcome to the real world, there is no VM here, just real machines. C
    assume you know what you are doing, and you shouldn't use functions like
    strncpy(), unless you know how it works.

    C don't have exception handling, so you better get started without it,
    doing it the C way, means propagating return codes all over the place.

    --
    Tor < | tr i-za-h a-z>
    Tor Rustad, Nov 7, 2007
    #12
  13. "Lambda" <> a écrit dans le message de news:
    ...
    > When I call the standard strncpy function, I provide it a negative
    > argument,
    > such as:
    >
    > strncpy(s, ct, -1)
    >
    > I compile the code with gcc, when I run, it says "Segmentation fault".
    > Do you think it's ok? I try this to see how the library handle invalid
    > parameter.


    strncpy does *not* do what you think it does.

    Read the manual page for strncpy.

    Until you understand what strncpy does, you should not use it.

    When you understand the precise semantics of strncpy, you should realize
    that it is very unlikely you will ever need to use this function. You may
    think it is useful for limited string copy, but it is very error prone for
    doing that, and almost always requires extra code.

    If you want to do a limited string copy, consider BSD's strlcpy as defined
    in http://www.openbsd.org/cgi-bin/man.cgi?query=strlcpy or
    http://en.wikipedia.org/wiki/Strlcpy

    --
    Chqrlie.
    Charlie Gordon, Nov 8, 2007
    #13
  14. "santosh" <> a écrit dans le message de news:
    fgp8jp$joa$...
    > On Tuesday 06 Nov 2007 1:26 pm Lambda <> wrote in
    > article <>:
    >
    >> When I call the standard strncpy function, I provide it a negative
    >> argument,
    >> such as:
    >>
    >> strncpy(s, ct, -1)

    >
    > Here -1 is converted to the type size_t which is an unsigned integer.
    > Thus this actually results in strncpy receiving a very large positive
    > value. The segmentation fault is probably caused by strncpy trying to
    > read memory far beyond the legal limits.


    Invoking strncpy with a size of -1 is almost guaranteed to cause undefined
    behaviour of the worst kind. Segmentation fault is not unexpected.
    Contrary to what you suggest, the crash is most likely caused by strncpy
    trying to pad the destination with '\0' upto size (SIZE_MAX) thereby
    attempting to write a huge chunk of memory (possibly larger than all
    adressable memory) to which write access is unlikely to have been granted.

    If you are not familiar with the semantics of strncpy, I urge you to read
    the manual or the Standard.

    --
    Chqrlie.
    Charlie Gordon, Nov 8, 2007
    #14
  15. Lambda

    santosh Guest

    On Thursday 08 Nov 2007 8:38 pm Charlie Gordon <> wrote
    in article <47332664$0$30947$>:

    > "santosh" <> a écrit dans le message de news:
    > fgp8jp$joa$...
    >> On Tuesday 06 Nov 2007 1:26 pm Lambda <> wrote
    >> in article <>:
    >>
    >>> When I call the standard strncpy function, I provide it a negative
    >>> argument,
    >>> such as:
    >>>
    >>> strncpy(s, ct, -1)

    >>
    >> Here -1 is converted to the type size_t which is an unsigned integer.
    >> Thus this actually results in strncpy receiving a very large positive
    >> value. The segmentation fault is probably caused by strncpy trying to
    >> read memory far beyond the legal limits.

    >
    > Invoking strncpy with a size of -1 is almost guaranteed to cause
    > undefined
    > behaviour of the worst kind. Segmentation fault is not unexpected.
    > Contrary to what you suggest, the crash is most likely caused by
    > strncpy trying to pad the destination with '\0' upto size (SIZE_MAX)
    > thereby attempting to write a huge chunk of memory (possibly larger
    > than all adressable memory) to which write access is unlikely to have
    > been granted.
    >
    > If you are not familiar with the semantics of strncpy, I urge you to
    > read the manual or the Standard.


    Thanks! I stand corrected. You and Malcolm are in a class by
    yourselves! :)
    santosh, Nov 8, 2007
    #15
  16. Lambda

    Ben Pfaff Guest

    Lambda <> writes:

    > When I call the standard strncpy function, I provide it a negative
    > argument,
    > such as:
    >
    > strncpy(s, ct, -1)


    strncpy cannot have a negative third argument, because the third
    parameter has an unsigned type. C specifies that -1 will be
    converted to the maximum value of size_t, so that this call to
    strncpy will likely try to overwrite all memory.

    There is occasionally a good reason to use strncpy(). However:

    * Using strncpy() into a large buffer can be very inefficient.
    strncpy() always writes to every byte in the destination
    buffer, which can waste a lot of time if the destination
    buffer is much longer than the source string.

    * If the source string is longer than the size of the
    destination buffer, then strncpy() doesn't write a
    terminating null. So a call to strncpy() must be followed
    by explicitly writing a null terminator at the end of the
    destination buffer in most cases.


    --
    char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[]
    ={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa67f6aaa,0xaa9aa9f6,0x11f6},*p
    =b,i=24;for(;p+=!*p;*p/=4)switch(0[p]&3)case 0:{return 0;for(p--;i--;i--)case+
    2:{i++;if(i)break;else default:continue;if(0)case 1:putchar(a[i&15]);break;}}}
    Ben Pfaff, Nov 8, 2007
    #16
    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. Dietrich
    Replies:
    1
    Views:
    619
    Joe Smith
    Jul 22, 2004
  2. Leon
    Replies:
    2
    Views:
    501
  3. Java Guy
    Replies:
    1
    Views:
    661
    Manish Pandit
    Oct 15, 2006
  4. =?ISO-8859-1?Q?KLEIN_St=E9phane?=
    Replies:
    3
    Views:
    430
    hanumizzle
    Oct 6, 2006
  5. Java Guy
    Replies:
    1
    Views:
    284
Loading...

Share This Page