strncpy and 'n'

Discussion in 'C Programming' started by nroberts, Feb 16, 2012.

  1. nroberts

    nroberts Guest

    Consider:

    char const* f(char const* incoming)
    {
    static char buf[MAX];

    strncpy(buf, incoming, strlen(incoming));
    }

    Is there ANY reason to use strncpy like that? I'm working on a
    project that has such uses all throughout it and before I tell the
    team leader that he's using a basic C function incorrectly I thought
    I'd make sure I'm right.
    nroberts, Feb 16, 2012
    #1
    1. Advertising

  2. nroberts <> writes:

    > Consider:
    >
    > char const* f(char const* incoming)
    > {
    > static char buf[MAX];
    >
    > strncpy(buf, incoming, strlen(incoming));
    > }
    >
    > Is there ANY reason to use strncpy like that?


    If you want to avoid havig the '\0' copied from the incoming text,
    and risk overrunning buf, there could be a point. But apart from that, no.

    I would rather use strncpy like this:

    strncpy (buf, incoming, MAX);
    buf[MAX] = 0;

    > I'm working on a project that has such uses all throughout it and
    > before I tell the team leader that he's using a basic C function
    > incorrectly I thought I'd make sure I'm right.


    Submit some code to www.thedailywtf.com :)




    --
    /Wegge

    Leder efter redundant peering af dk.*,linux.debian.*
    Anders Wegge Keller, Feb 16, 2012
    #2
    1. Advertising

  3. nroberts <> writes:
    > Consider:
    >
    > char const* f(char const* incoming)
    > {
    > static char buf[MAX];
    >
    > strncpy(buf, incoming, strlen(incoming));
    > }
    >
    > Is there ANY reason to use strncpy like that? I'm working on a
    > project that has such uses all throughout it and before I tell the
    > team leader that he's using a basic C function incorrectly I thought
    > I'd make sure I'm right.


    There's rarely *any* reason to use strncpy(). It's not a "safer"
    version of strcpy(); it's a quite different function. It can leave
    the target buffer without a terminating '\0' (i.e., not a string),
    or it can pad it with multiple needless '\0' bytes.

    For that particular call, if strlen(incoming) is 10, for example,
    it will only copy 10 bytes; it will not copy the terminating '\0'.
    If that's what you want (either buf doesn't need to be a string, or
    some other code supplies the '\0'), then memcpy() makes more sense.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Will write code for food.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Feb 16, 2012
    #3
  4. nroberts

    Guest

    nroberts <> wrote:
    > Consider:
    >
    > char const* f(char const* incoming)
    > {
    > static char buf[MAX];
    >
    > strncpy(buf, incoming, strlen(incoming));
    > }
    >
    > Is there ANY reason to use strncpy like that?


    Maybe, but almost certainly not. If the incoming string is longer than
    MAX bytes, you get a buffer overflow, which is very bad. If it happens
    to be exactly MAX characters long, you get an unterminated string in
    buf, which is bad if the following code (you don't show any, but I
    presume there is some or the function is completely pointless) expects
    to treat it as a string. And if the incoming string is less than MAX
    bytes, since the code doesn't copy the null byte, you get whatever is
    leftover in buf tacked on to the end. (buf is initialized to all null
    bytes, but since it's static, that only happens once, not on each call.)
    --
    Larry Jones

    Oh yeah? You just wait! -- Calvin
    , Feb 16, 2012
    #4
  5. nroberts

    A. K. Guest

    On 16.02.2012 18:57, Anders Wegge Keller wrote:
    > nroberts<> writes:
    >
    >> Consider:
    >>
    >> char const* f(char const* incoming)
    >> {
    >> static char buf[MAX];
    >>
    >> strncpy(buf, incoming, strlen(incoming));
    >> }
    >>
    >> Is there ANY reason to use strncpy like that?

    >
    > If you want to avoid havig the '\0' copied from the incoming text,
    > and risk overrunning buf, there could be a point. But apart from that, no.
    >
    > I would rather use strncpy like this:
    >
    > strncpy (buf, incoming, MAX);
    > buf[MAX] = 0;


    buffer overflow !!! :eek:)

    >
    >> I'm working on a project that has such uses all throughout it and
    >> before I tell the team leader that he's using a basic C function
    >> incorrectly I thought I'd make sure I'm right.

    >
    > Submit some code to www.thedailywtf.com :)
    >
    >
    >
    >
    A. K., Feb 16, 2012
    #5
  6. "A. K." <> writes:

    > On 16.02.2012 18:57, Anders Wegge Keller wrote:


    >> buf[MAX] = 0;


    buffer overflow !!! :eek:)

    If you got to have them, better decide yourself where to have them. I
    pledge insanity in the act.

    --
    /Wegge

    Leder efter redundant peering af dk.*,linux.debian.*
    Anders Wegge Keller, Feb 16, 2012
    #6
  7. nroberts schrieb:
    > Consider:
    >
    > char const* f(char const* incoming)
    > {
    > static char buf[MAX];
    >
    > strncpy(buf, incoming, strlen(incoming));
    > }
    >
    > Is there ANY reason to use strncpy like that? I'm working on a
    > project that has such uses all throughout it and before I tell the
    > team leader that he's using a basic C function incorrectly I thought
    > I'd make sure I'm right.


    He has probably heard that strcpy() is bad and that he should use
    strncpy().

    Markus
    Markus Schaub, Feb 16, 2012
    #7
  8. On Feb 16, 6:01 pm, Keith Thompson <> wrote:
    >
    > There's rarely *any* reason to use strncpy().  It's not a "safer"
    > version of strcpy(); it's a quite different function.  It can leave
    > the target buffer without a terminating '\0' (i.e., not a string),
    > or it can pad it with multiple needless '\0' bytes.
    >

    It's designed for databases with fixed fields and non-nul terminated
    strings. The padding zeros aren't unnecessary, because often these
    databases do a quick match or lookup by applying some algorithm to the
    whole field.
    Malcolm McLean, Feb 16, 2012
    #8
  9. nroberts

    Ben Pfaff Guest

    nroberts <> writes:

    > char const* f(char const* incoming)
    > {
    > static char buf[MAX];
    >
    > strncpy(buf, incoming, strlen(incoming));
    > }
    >
    > Is there ANY reason to use strncpy like that?


    It looks very odd. I think it would be equivalent code if you
    replaced "strncpy" by "memcpy" here.

    The behavior here make sense for the first call to the function,
    if strlen(incoming) < MAX, but it will be strange on subsequent
    calls.
    --
    "The fact that there is a holy war doesn't mean that one of the sides
    doesn't suck - usually both do..."
    --Alexander Viro
    Ben Pfaff, Feb 16, 2012
    #9
  10. On 16-Feb-12 11:05, nroberts wrote:
    > Consider:
    >
    > char const* f(char const* incoming)
    > {
    > static char buf[MAX];
    >
    > strncpy(buf, incoming, strlen(incoming));
    > }
    >
    > Is there ANY reason to use strncpy like that? I'm working on a
    > project that has such uses all throughout it and before I tell the
    > team leader that he's using a basic C function incorrectly I thought
    > I'd make sure I'm right.


    Assuming this is representative of the actual code, it's clearly wrong
    because strncpy() will overflow buf if strlen(incoming)+1 is greater
    than MAX. This means it is no better than strcpy(buf, incoming).

    The correct way to write this would be:

    char const* f(char const* incoming)
    {
    static char buf[MAX];

    strncpy(buf, incoming, MAX);
    }

    Unlike the above code, this guarantees the copy will not overflow buf.

    S

    --
    Stephen Sprunk "God does not play dice." --Albert Einstein
    CCIE #3723 "God is an inveterate gambler, and He throws the
    K5SSS dice at every possible opportunity." --Stephen Hawking
    Stephen Sprunk, Feb 16, 2012
    #10
  11. nroberts

    ImpalerCore Guest

    On Feb 16, 12:05 pm, nroberts <> wrote:
    > Consider:
    >
    > char const* f(char const* incoming)
    > {
    >   static char buf[MAX];
    >
    >   strncpy(buf, incoming, strlen(incoming));
    >
    > }
    >
    > Is there ANY reason to use strncpy like that?  I'm working on a
    > project that has such uses all throughout it and before I tell the
    > team leader that he's using a basic C function incorrectly I thought
    > I'd make sure I'm right.


    When you're working with fixed width character buffers, use a fixed
    width strlen.

    size_t c_strnlen( const char* str, size_t n )
    {
    const char* p;
    p = memchr( str, '\0', n );
    return p ? (size_t)( p - str ) : n;
    }

    Then use the following

    strncpy(buf, incoming, c_strnlen(incoming, sizeof (buf)));

    Of course, this replaces the potential of a buffer overrun with
    truncation, which can lead to other subtle problems.

    An alternative is to use something like 'strlcpy', if you want to
    guarantee a '\0' character at the end of the string.

    Best regards,
    John D.
    ImpalerCore, Feb 16, 2012
    #11
  12. nroberts

    A. K. Guest

    On 16.02.2012 19:34, Anders Wegge Keller wrote:
    > "A. K."<> writes:
    >
    >> On 16.02.2012 18:57, Anders Wegge Keller wrote:

    >
    >>> buf[MAX] = 0;

    >
    > buffer overflow !!! :eek:)
    >
    > If you got to have them, better decide yourself where to have them. I
    > pledge insanity in the act.
    >

    guess where I have learnt that this produces an overflow?
    :eek:)))
    A. K., Feb 16, 2012
    #12
  13. Malcolm McLean <> writes:
    > On Feb 16, 6:01 pm, Keith Thompson <> wrote:
    >> There's rarely *any* reason to use strncpy().  It's not a "safer"
    >> version of strcpy(); it's a quite different function.  It can leave
    >> the target buffer without a terminating '\0' (i.e., not a string),
    >> or it can pad it with multiple needless '\0' bytes.
    >>

    > It's designed for databases with fixed fields and non-nul terminated
    > strings. The padding zeros aren't unnecessary, because often these
    > databases do a quick match or lookup by applying some algorithm to the
    > whole field.


    Yes, the padding zeros are necessary *if* you're dealing with that
    kind of data structure.

    I suspect that strncpy() is used incorrectly, under the assumption
    that it's a "safer" strcpy(), more often than it's used correctly.
    IMHO it shouldn't be in the standard library, at least not with
    that name.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Will write code for food.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Feb 16, 2012
    #13
  14. nroberts

    Ike Naar Guest

    On 2012-02-16, Stephen Sprunk <> wrote:
    > On 16-Feb-12 11:05, nroberts wrote:
    >> char const* f(char const* incoming)
    >> {
    >> static char buf[MAX];
    >>
    >> strncpy(buf, incoming, strlen(incoming));
    >> }
    >>

    > Assuming this is representative of the actual code, it's clearly wrong
    > because strncpy() will overflow buf if strlen(incoming)+1 is greater
    > than MAX. This means it is no better than strcpy(buf, incoming).


    Nit: it wil overflow if strlen(incoming) is greater than MAX.
    It wil not overflow if strlen(incoming) equals MAX.
    In that case, it will leave an unterminated string in buf,
    but most people wouldn't call that an overflow.
    Ike Naar, Feb 16, 2012
    #14
  15. On Feb 16, 5:05 pm, nroberts <> wrote:
    > Consider:
    >
    > char const* f(char const* incoming)
    > {
    >   static char buf[MAX];
    >
    >   strncpy(buf, incoming, strlen(incoming));
    >
    > }
    >
    > Is there ANY reason to use strncpy like that?


    no. Besides all the other problems the function doesn't return
    anything and buf[] is inaccessible. I suspect you meant to return
    &buf[0].


    >  I'm working on a
    > project that has such uses all throughout it and before I tell the
    > team leader that he's using a basic C function incorrectly I thought
    > I'd make sure I'm right.
    Nick Keighley, Feb 17, 2012
    #15
  16. On Feb 16, 10:20 pm, Keith Thompson <> wrote:
    >
    > I suspect that strncpy() is used incorrectly, under the assumption
    > that it's a "safer" strcpy(), more often than it's used correctly.
    > IMHO it shouldn't be in the standard library, at least not with
    > that name.
    >

    You're right.
    There's no point providing strncpy() but not functions like hash() and
    faststrncmpwithtrailingzeros() to actually use fixed width strings.
    --
    Malcolm's website
    http://www.malcommclean.site11.com/www
    Malcolm McLean, Feb 17, 2012
    #16
  17. nroberts

    James Kuyper Guest

    On 02/17/2012 07:19 AM, Malcolm McLean wrote:
    > On Feb 16, 10:20�pm, Keith Thompson <> wrote:
    >>
    >> I suspect that strncpy() is used incorrectly, under the assumption
    >> that it's a "safer" strcpy(), more often than it's used correctly.
    >> IMHO it shouldn't be in the standard library, at least not with
    >> that name.
    >>

    > You're right.
    > There's no point providing strncpy() but not functions like hash() and
    > faststrncmpwithtrailingzeros() to actually use fixed width strings.


    What would be the benefits of using faststrncmpwithtrailingzeros()
    rather than memcmp() be?
    --
    James Kuyper
    James Kuyper, Feb 17, 2012
    #17
  18. On Feb 17, 3:04 pm, James Kuyper <> wrote:
    >
    > What would be the benefits of using faststrncmpwithtrailingzeros()
    > rather than memcmp() be?
    >

    That's a point. It documents that you're doing a string compare, but
    actually it's the same as memcmp(). On most platforms, it will need
    guaranteed integer-aligned fields to be fast, however. That's not
    something it's easy to specify in the C standard.
    --
    Vist my website. Play the Alice in Wonderland Card game
    http://www.malcommclean.site11.com/www
    Malcolm McLean, Feb 17, 2012
    #18
  19. On Feb 17, 3:04 pm, James Kuyper <> wrote:
    >
    > What would be the benefits of using faststrncmpwithtrailingzeros()
    > rather than memcmp() be?
    >

    If you have long fields with mainly short contents, it could also be
    faster, since it can terminate at the first pair of nul bytes.
    Malcolm McLean, Feb 17, 2012
    #19
  20. nroberts

    James Kuyper Guest

    On 02/17/2012 02:22 PM, Malcolm McLean wrote:
    > On Feb 17, 3:04�pm, James Kuyper <> wrote:
    >>
    >> What would be the benefits of using faststrncmpwithtrailingzeros()
    >> rather than memcmp() be?
    >>

    > If you have long fields with mainly short contents, it could also be
    > faster, since it can terminate at the first pair of nul bytes.


    If you know that the the end of the string will be determined either by
    the end of a fixed-length field, or by a terminating null character,
    strncmp(). If you want to check the entire length of the fixed length
    field, regardless of null terminators, memcmp() would do. I don't think
    that there's sufficient need for a function whose behavior falls
    between those two extremes, to make it a standard library function.
    --
    James Kuyper
    James Kuyper, Feb 17, 2012
    #20
    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. Simon
    Replies:
    3
    Views:
    696
    Simon
    Sep 6, 2004
  2. Replies:
    4
    Views:
    1,121
    Dave Moore
    Feb 1, 2005
  3. Re: bizzare strncpy()

    , Jul 9, 2003, in forum: C Programming
    Replies:
    4
    Views:
    362
    Martin Ambuhl
    Jul 9, 2003
  4. Vijay Kumar R Zanvar

    Code Review: strncpy

    Vijay Kumar R Zanvar, Jan 14, 2004, in forum: C Programming
    Replies:
    30
    Views:
    3,980
  5. Barry

    strncpy() and null terminated strings

    Barry, Apr 8, 2004, in forum: C Programming
    Replies:
    4
    Views:
    1,117
    Malcolm
    Apr 8, 2004
Loading...

Share This Page