Re: I need help

Discussion in 'C Programming' started by janus, May 14, 2011.

  1. janus

    janus Guest

    Another thing it is likely to print is "SIGSEGV" or "SIGBUS" or
    "General Protection Fault" or something along those lines. The
    anonymous array created by the string literal is not `const', but
    that's just an accident of history. Trying to modify such an array
    yields undefined behavior -- and indeed, plenty of compilers will
    put the arrays in read-only memory. (This allows them to save space
    by allocating just one array to hold both of "over" and "recover".)

    I am a bit confused by the above...

    Is the correct?

    char* string = "NEW";
    strcat(string, "Jersey");

    If string is in read-only memory, could it still support things like concatenation?

    Janus
     
    janus, May 14, 2011
    #1
    1. Advertising

  2. "janus" <> schrieb im Newsbeitrag
    news:...
    ....
    > Is the correct?
    >
    > char* string = "NEW";
    > strcat(string, "Jersey");
    >
    > If string is in read-only memory, could it still support things like
    > concatenation?
    >
    > Janus


    read-only memory does not support concatenation either. And there is yet
    another problem when you code:

    char string[] = "NEW";
    strcat(string, "Jersey");

    You do not reserve space to hold the concatenated string. Here is how you
    could do it:

    char string[10] = "NEW";
    strcat(string, "Jersey");

    However strcat has the danger to run out of string size. I always code that:

    char string[10] = "NEW";
    strncat(string, "Jersey", sizeof(string) - strlen(string) - 1);

    or with a macro:

    #define STRNCAT(a, b) strncat(a, b, sizeof(a) - strlen(a) - 1)
    char string[10] = "NEW";
    STRNCAT(string, "Jersey");
     
    Heinrich Wolf, May 14, 2011
    #2
    1. Advertising

  3. janus <> writes:
    > Another thing it is likely to print is "SIGSEGV" or "SIGBUS" or
    > "General Protection Fault" or something along those lines. The
    > anonymous array created by the string literal is not `const', but
    > that's just an accident of history. Trying to modify such an array
    > yields undefined behavior -- and indeed, plenty of compilers will
    > put the arrays in read-only memory. (This allows them to save space
    > by allocating just one array to hold both of "over" and "recover".)
    >
    > I am a bit confused by the above...
    >
    > Is the correct?
    >
    > char* string = "NEW";
    > strcat(string, "Jersey");
    >
    > If string is in read-only memory, could it still support things like
    > concatenation?


    No.

    On my system, a program containing those two lines died with a
    segmentation fault.

    But of course that's not the only possible result. String literals
    (more accurately, the static arrays associated with them) aren't
    *necessarily* stored in read-only memory. The strcat() call will
    attempt to store the 7 characters of "Jersey" (6 plus the trailing
    '\0') at locations starting after the 'W' in "NEW". This might
    appear to work, if that area of memory happens to be writable
    and happens not to be used for anything else. On the other hand,
    it could clobber some other variable, or write over some internal
    information (such as the function's return address), with arbitrarily
    bad results that might not even appear until later.

    And the phrase "will attempt" above isn't strictly correct. Since
    the behavior is undefined, strcat() could conceivably detect that it
    won't be able to write the characters and do something else instead.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, May 14, 2011
    #3
  4. janus

    Phil Carmody Guest

    "Heinrich Wolf" <> writes:
    > "janus" <> schrieb im Newsbeitrag
    > news:...
    > ...
    > > Is the correct?
    > >
    > > char* string = "NEW";
    > > strcat(string, "Jersey");
    > >
    > > If string is in read-only memory, could it still support things like
    > > concatenation?
    > >
    > > Janus

    >
    > read-only memory does not support concatenation either. And there is
    > yet another problem when you code:
    >
    > char string[] = "NEW";
    > strcat(string, "Jersey");
    >
    > You do not reserve space to hold the concatenated string. Here is how
    > you could do it:
    >
    > char string[10] = "NEW";
    > strcat(string, "Jersey");
    >
    > However strcat has the danger to run out of string size. I always code that:
    >
    > char string[10] = "NEW";
    > strncat(string, "Jersey", sizeof(string) - strlen(string) - 1);


    Why do you want to scan accross "NEW" twice? Once in the strlen, and
    once in the strncat.

    Phil
    --
    "At least you know where you are with Microsoft."
    "True. I just wish I'd brought a paddle." -- Matthew Vernon
     
    Phil Carmody, May 15, 2011
    #4
  5. "Phil Carmody" <> schrieb im Newsbeitrag
    news:...
    ....
    > Why do you want to scan accross "NEW" twice? Once in the strlen, and
    > once in the strncat.


    I know that I could save some microseconds with

    size_t l = strlen(a);
    strncat(a + l, b, sizeof(a) - l - 1);

    but STRNCAT has done a good job many years and is easy to read.
     
    Heinrich Wolf, May 15, 2011
    #5
  6. janus

    Eric Sosman Guest

    On 5/14/2011 2:15 PM, janus wrote:
    > Another thing it is likely to print is "SIGSEGV" or "SIGBUS" or
    > "General Protection Fault" or something along those lines. The
    > anonymous array created by the string literal is not `const', but
    > that's just an accident of history. Trying to modify such an array
    > yields undefined behavior -- and indeed, plenty of compilers will
    > put the arrays in read-only memory. (This allows them to save space
    > by allocating just one array to hold both of "over" and "recover".)
    >
    > I am a bit confused by the above...


    It is customary to mark the material you quote, making it
    distinguishable from material of your own authorship. See those
    greater-than signs at the left margin? Most news clients or mail
    clients will insert them for you.

    It is also customary to attribute the quoted material to its
    author (or authors), so that readers aren't misled into thinking
    its your own. See that "On...janus wrote:" line at the top?
    Again, most news clients or mail clients will insert such lines
    for you.

    To use the medium effectively, first learn to use the medium.

    > Is the correct?
    >
    > char* string = "NEW";
    > strcat(string, "Jersey");


    Undefined behavior.

    > If string is in read-only memory, could it still support things like concatenation?


    No.

    Nor should it. Think of it this way: A string literal (when
    used this way) is notionally a constant, much like 42 or 3.14. If
    you start modifying constants, things will become very confusing
    very rapidly:

    int i = 6;
    6 *= 7; /* not legal; just imagine */
    int j = 6; /* does j have the value forty-two? */

    Similarly with string constants: By concatenating to a string (or
    by changing one or more of its existing characters), you change
    the value of that string. So:

    char *message = "Hello, world!";
    strcpy(message, "Go to Hell!"); /* not legal; just imagine */
    puts(message); /* friendly, or confrontational? */

    You don't (or shouldn't) want to change a constant, and C doesn't
    promise that an attempt to do so will succeed. (Doesn't promise
    anything at all about what will happen, actually.)

    --
    Eric Sosman
    d
     
    Eric Sosman, May 15, 2011
    #6
  7. janus

    Eric Sosman Guest

    On 5/14/2011 2:29 PM, Heinrich Wolf wrote:
    >[...]
    > However strcat has the danger to run out of string size. I always code
    > that:
    >
    > char string[10] = "NEW";
    > strncat(string, "Jersey", sizeof(string) - strlen(string) - 1);
    >
    > or with a macro:
    >
    > #define STRNCAT(a, b) strncat(a, b, sizeof(a) - strlen(a) - 1)
    > char string[10] = "NEW";
    > STRNCAT(string, "Jersey");


    If you like this sort of thing, so be it -- I'm not convinced
    there's much value in using training wheels, but tastes vary.

    However, you ought to mention that this STRNCAT macro relies
    on the pre-existing '\0' at the end of the output array. If
    string[9] were '?' instead of '\0', STRNCAT would run happily but
    leave you with a non-terminated string, just waiting to cause
    unpleasant surprises later.

    --
    Eric Sosman
    d
     
    Eric Sosman, May 15, 2011
    #7
  8. "Eric Sosman" <> schrieb im Newsbeitrag
    news:iqog3e$27h$...
    ....
    > However, you ought to mention that this STRNCAT macro relies
    > on the pre-existing '\0' at the end of the output array. If
    > string[9] were '?' instead of '\0', STRNCAT would run happily but
    > leave you with a non-terminated string, just waiting to cause
    > unpleasant surprises later.

    ....
    No! strncat guarantees to append a terminating '\0' character, even if it
    needs to truncate the source string. That is the difference to strncpy. You
    do net need to memset(output, 0 sizeof(output)); The only prerequisite is,
    that output is terminated by a single '\0' before. But that is the same with
    strcat.
     
    Heinrich Wolf, May 15, 2011
    #8
  9. janus

    Eric Sosman Guest

    On 5/15/2011 8:30 AM, Heinrich Wolf wrote:
    >
    > "Eric Sosman" <> schrieb im Newsbeitrag
    > news:iqog3e$27h$...
    > ...
    >> However, you ought to mention that this STRNCAT macro relies
    >> on the pre-existing '\0' at the end of the output array. If
    >> string[9] were '?' instead of '\0', STRNCAT would run happily but
    >> leave you with a non-terminated string, just waiting to cause
    >> unpleasant surprises later.

    > ...
    > No! strncat guarantees to append a terminating '\0' character, even if
    > it needs to truncate the source string. That is the difference to
    > strncpy. You do net need to memset(output, 0 sizeof(output)); The only
    > prerequisite is, that output is terminated by a single '\0' before. But
    > that is the same with strcat.


    My apologies: I confused `strncat' with `strncpy'.

    --
    Eric Sosman
    d
     
    Eric Sosman, May 15, 2011
    #9
  10. janus

    Phil Carmody Guest

    "Heinrich Wolf" <> writes:

    > "Phil Carmody" <> schrieb im
    > Newsbeitrag news:...
    > ...
    > > Why do you want to scan accross "NEW" twice? Once in the strlen, and
    > > once in the strncat.

    >
    > I know that I could save some microseconds


    You knew you always knew the ratio of the length of the left
    string compared to the right string? Wow, you're a lucky man.
    I wish I could be so certain that arbitrary input was so
    predictable.

    Phil
    --
    "At least you know where you are with Microsoft."
    "True. I just wish I'd brought a paddle." -- Matthew Vernon
     
    Phil Carmody, May 16, 2011
    #10
  11. janus

    Phil Carmody Guest

    Eric Sosman <> writes:

    > On 5/15/2011 8:30 AM, Heinrich Wolf wrote:
    > >
    > > "Eric Sosman" <> schrieb im Newsbeitrag
    > > news:iqog3e$27h$...
    > > ...
    > >> However, you ought to mention that this STRNCAT macro relies
    > >> on the pre-existing '\0' at the end of the output array. If
    > >> string[9] were '?' instead of '\0', STRNCAT would run happily but
    > >> leave you with a non-terminated string, just waiting to cause
    > >> unpleasant surprises later.

    > > ...
    > > No! strncat guarantees to append a terminating '\0' character, even if
    > > it needs to truncate the source string. That is the difference to
    > > strncpy. You do net need to memset(output, 0 sizeof(output)); The only
    > > prerequisite is, that output is terminated by a single '\0' before. But
    > > that is the same with strcat.

    >
    > My apologies: I confused `strncat' with `strncpy'.


    Votes for abolishing srtncat?

    1 here; I trust the above is enough of a reason to come on board, and from
    what Heinrich has posted, hopefully there's a 3rd vote too.

    Phil
    --
    "At least you know where you are with Microsoft."
    "True. I just wish I'd brought a paddle." -- Matthew Vernon
     
    Phil Carmody, May 16, 2011
    #11
  12. janus

    Ian Collins Guest

    On 05/15/11 06:29 AM, Heinrich Wolf wrote:
    >
    > or with a macro:
    >
    > #define STRNCAT(a, b) strncat(a, b, sizeof(a) - strlen(a) - 1)
    > char string[10] = "NEW";
    > STRNCAT(string, "Jersey");


    That macro would go horribly (and silently) wrong if

    a) 'a' wasn't a fixed sized array, or
    b) it was, but the definition wasn't visible when the macro was expanded.

    --
    Ian Collins
     
    Ian Collins, May 16, 2011
    #12
  13. Ian Collins <> writes:

    > On 05/15/11 06:29 AM, Heinrich Wolf wrote:
    >>
    >> or with a macro:
    >>
    >> #define STRNCAT(a, b) strncat(a, b, sizeof(a) - strlen(a) - 1)
    >> char string[10] = "NEW";
    >> STRNCAT(string, "Jersey");

    >
    > That macro would go horribly (and silently) wrong if
    >
    > a) 'a' wasn't a fixed sized array, or


    I don't think "fixed size" conveys what you want. It might be seen to
    contrast with variably modified arrays, but they work just as well (or
    as badly) as any other. I think you wanted to suggest that 'a' might be
    a pointer rather than an array. If not, I'll add:

    a1) 'a' expands not to the name of an array but to a pointer expression.

    > b) it was, but the definition wasn't visible when the macro was expanded.


    I can't think how this could go silently wrong, but it sounds bad! I'd
    add

    c) strlen(a) >= sizeof(a)

    simply because it goes wrong in a way that is often unexpected.

    --
    Ben.
     
    Ben Bacarisse, May 16, 2011
    #13
  14. janus

    Ian Collins Guest

    On 05/16/11 02:45 PM, pete wrote:
    > Ian Collins wrote:
    >>
    >> On 05/15/11 06:29 AM, Heinrich Wolf wrote:
    >>>
    >>> or with a macro:
    >>>
    >>> #define STRNCAT(a, b) strncat(a, b, sizeof(a) - strlen(a) - 1)
    >>> char string[10] = "NEW";
    >>> STRNCAT(string, "Jersey");

    >>
    >> That macro would go horribly (and silently) wrong if
    >>
    >> a) 'a' wasn't a fixed sized array, or
    >> b) it was, but the definition wasn't visible
    >> when the macro was expanded.

    >
    > If (a) was a fixed sized array,
    > but the definition wasn't visible when the macro was expanded,
    > then (a) would be an incomplete type
    > and (sizeof a) would cause the generation of a diagnostic message,
    > rather than go silently wrong.


    Well OK, I was thinking an extern pointer declaration, but that would be
    a messy mix.

    --
    Ian Collins
     
    Ian Collins, May 16, 2011
    #14
  15. "Ian Collins" <> schrieb im Newsbeitrag
    news:...
    > On 05/15/11 06:29 AM, Heinrich Wolf wrote:
    >>
    >> or with a macro:
    >>
    >> #define STRNCAT(a, b) strncat(a, b, sizeof(a) - strlen(a) - 1)
    >> char string[10] = "NEW";
    >> STRNCAT(string, "Jersey");

    >
    > That macro would go horribly (and silently) wrong if
    >
    > a) 'a' wasn't a fixed sized array, or
    > b) it was, but the definition wasn't visible when the macro was expanded.
    >
    > --
    > Ian Collins


    You must not use the macro STRNCAT in e.g. this case:

    void a_procedure(char *a)
    {
    STRNCAT(a, "Jersey");
    }

    int main(void)
    {

    char string[10] = "NEW";
    a_procedure(string);
    }

    Here sizeof(a) is the size of a pointer and not the size of string. Instead
    you could do it without the macro:

    void a_procedure(char *a, size_t size)
    {
    strncat(a, "Jersey", size - strlen(a) - 1);
    }

    int main(void)
    {

    char string[10] = "NEW";
    a_procedure(string, sizeof(string));
    }
     
    Heinrich Wolf, May 16, 2011
    #15
    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. TN Bella
    Replies:
    1
    Views:
    2,477
    Edward
    Jun 18, 2004
  2. Teep
    Replies:
    2
    Views:
    767
    Larry Marburger
    Jun 21, 2004
  3. John
    Replies:
    1
    Views:
    402
    John C. Bollinger
    Aug 19, 2004
  4. =?Utf-8?B?Q2hyaXM=?=

    Help Help. I really need some help with this

    =?Utf-8?B?Q2hyaXM=?=, Jan 31, 2007, in forum: ASP .Net
    Replies:
    3
    Views:
    568
    =?Utf-8?B?SmFzb24gVmVybWlsbGlvbg==?=
    Jan 31, 2007
  5. ElementX
    Replies:
    9
    Views:
    497
    RedGrittyBrick
    Oct 1, 2008
Loading...

Share This Page