Thread: problem with strncat command

  1. #1
    Registered User
    Join Date
    Sep 2011
    Posts
    24

    problem with strncat command

    The code below supposed to provide
    str1 = ilikeyou.c
    str2 = .com as str2 should not affect by strncat command
    but it shows str1 = iloveyou.c and str2 = c

    I wonder why str2 is only c when it supposed to be .com

    Code:
    main ()
    {
    char *str1 = "ilikeyou"
    char *str2 = ".com"
    clrscr ();
    printf ("your two lines are \n %s \n %s", str1,str2);
    strncat (str1,str2,2);
    printf ("\nYour new two lines are \n %s \n %s", str1,str2);
    getch ();
    return 0;
    }

  2. #2
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    You need to learn how pointers differ from arrays; you are writing over memory you did NOT allocate.
    Also learn to indent your code!

    Tim S.

    Code:
    #include <stdio.h>
    #include <string.h>
    
    /* Needed because I use a compiler written in this century */
    void clrscr (void) {};
    /* end of obsolete functions */
    
    int main (void) {
        char str1[12] = "ilikeyou";
        char str2[12] = ".com";
        clrscr ();
        printf ("your two lines are \n %s \n %s", str1,str2);
        strncat (str1,str2,2);
        printf ("\nYour new two lines are \n %s \n %s", str1,str2);
        getchar ();
        return 0;
    }
    Last edited by stahta01; 10-13-2011 at 04:15 PM.

  3. #3
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    When using strncat() the onus on you is to ensure the buffer (str1) is long enough to contain every character that might be written to it. You have not done that.

    You have initialized str1 and str2 using string literals. Which means the buffers they identify are of fixed length. Appending any characters to the end of str1 (which is what your call of strncat() does) runs past the end of that buffer. That is undefined behaviour.

    It just so happens your compiler has placed the buffers for str1 and str2 adjacent in memory. Hence your observed behaviour. Reformatting your hard drive would be another perfectly correct result.

    Oh: it is also not smart to omit the return type (int) from main. printf() also requires <stdio.h> and strncat() requires <string.h>, otherwise your code can compile but still not work correctly. clrscr() and getch() are grossly non-standard.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  4. #4
    ... kermit's Avatar
    Join Date
    Jan 2003
    Posts
    1,534
    The code you posted will not even compile (you are missing some semi-colons at the end of a couple of your assignment statements). As the previous posters mentioned, you need to allocate some space that your program can write to, otherwise you will end up with a segfault. Question 1.32 of the comp.lang.c FAQ begins to explain this problem in more detail. Follow the links at the bottom of that segment, and read through the FAQ in general; you will learn a lot from it.
    Last edited by kermit; 10-13-2011 at 04:21 PM.

  5. #5
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by learning_grc View Post
    The code below supposed to provide
    str1 = ilikeyou.c
    str2 = .com as str2 should not affect by strncat command
    but it shows str1 = iloveyou.c and str2 = c

    I wonder why str2 is only c when it supposed to be .com

    Code:
    main ()
    {
    char *str1 = "ilikeyou"
    char *str2 = ".com"
    clrscr ();
    printf ("your two lines are \n %s \n %s", str1,str2);
    strncat (str1,str2,2);
    printf ("\nYour new two lines are \n %s \n %s", str1,str2);
    getch ();
    return 0;
    }
    Ok... the others are making good points, but they're not really explaining what's happening.

    String literals are stored in a separate segment of the program image. Modern compilers will not let you change them. The only compiler I know that does allow it is TurboC... and it should have been dead and gone 2 decades ago.

    Anyway this is about how your data sits in memory... You create the two string literals right behind eachother so they sit in memory like this... ilikeyou0.com0 ... when you use strcat() you are adding the specified characters plus a trailing 0 to your string... So you end up with ilikeyou.c0om0 ... Now consider where the pointers are... the first pointer (str1) points at the i in "ilikeyou"... the second one starts out pointing at the . in ".com"... but when you overwrite it's data it ends up pointing at the c in ".c" since it's now at the same address.

    Thus you ended up clobbering your own data through a buffer overrun -- the common failing of all C strings worsened by the use of an ancient compiler that should never have existed in the first place.

  6. #6
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by CommonTater View Post
    Ok... the others are making good points, but they're not really explaining what's happening.
    As a matter of fact, I did describe what is happening.

    You have attempted to be more concrete, so you have described what happens with some modern compilers and some operating systems. There are other compilers and systems where the result differs from what you describe.

    Quote Originally Posted by CommonTater View Post
    Thus you ended up clobbering your own data through a buffer overrun -- the common failing of all C strings worsened by the use of an ancient compiler that should never have existed in the first place.
    While you're right in describing the original problem as a buffer overrun, everything you have said after the "--" is rubbish.

    Turbo C was state of the art in its day. In fact, for a while, it surpassed other compilers and its existence provided the impetus for several competing vendors - including Microsoft - to improve the quality of their products.

    The fact that technology (such as operating systems) and techniques (programming methods, compiler optimisations, etc) have advanced does justify your portrayal of Turbo C as a bucket of crap.

    All that has happened is that Turbo C became obsolete. Turbo C is over 20 years old, so that is hardly surprising. I will bet a lot of the products you advocate now will be obsolete 20 years from now. And there will probably be people, 20 years from now, showing small minded zealotry in their manners of describing current (as of today) techniques as rubbish.

    If you are going to be critical, be critical of people who choose to force others to use obsolete products when more modern and effective alternatives are readily available. But it would be advisable to abandon your habit of belittling the products themselves or (implicitly) those who created them.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  7. #7
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by grumpy View Post
    As a matter of fact, I did describe what is happening.
    So you decided to take a very general comment personally? hoookaaaay....

    You have attempted to be more concrete, so you have described what happens with some modern compilers and some operating systems. There are other compilers and systems where the result differs from what you describe.
    What I (and, yes, you) described is the only rational explanation of what happened... it makes no difference at all what a different compiler might have done... that one did, well, that.

    While you're right in describing the original problem as a buffer overrun, everything you have said after the "--" is rubbish.
    In your apparently not so humble opinion...

    Turbo C was state of the art in its day. In fact, for a while, it surpassed other compilers and its existence provided the impetus for several competing vendors - including Microsoft - to improve the quality of their products.

    The fact that technology (such as operating systems) and techniques (programming methods, compiler optimisations, etc) have advanced does justify your portrayal of Turbo C as a bucket of crap.
    I was just starting with Turbo Pascal when Turbo C was in it's heyday... I immediately ordered a copy, did a few things to check it out and rather quickly dumped it... All I needed to see it do was print a string of crap on my screen when Pascal --from the same company, btw-- got it right. Day one... string overrun... with absolutely no error trapping... still a problem in all C implementations today. If Borland hadn't murdered Pascal, I'd still be using it. (That is... if an up to date, Windows API compatible version of Pascal that wasn't bastardized by OOP was available, I'd be there in a heartbeat... and yes I know about FreePascal.)

    All that has happened is that Turbo C became obsolete. Turbo C is over 20 years old, so that is hardly surprising. I will bet a lot of the products you advocate now will be obsolete 20 years from now.
    I should certainly hope so...

    But then, I'm not time warping here... Pelles C is up to date (currently in revision with 6.50 RC4 in wide beta test) and pretty much state of the art where C is concerned. But it still has most of Turbo C's libraries on hand if you need them. And yes it suffers all of C's weaknesses when it comes to run-time screwups.

    And there will probably be people, 20 years from now, showing small minded zealotry in their manners of describing current (as of today) techniques as rubbish.
    Once again... I should certainly hope so.

    Lets be real plain... C is *rubbish*... Conceptually it's a graceful, elegant and small language which is highly capable at almost any level of programming... But it's stuck in the 70s... No *real* strings (not those stupid char[] arrays we play with), No bounds checks, No overflow or underflow checks, no exception handling... Really, if ever there was a truly brilliant concept crying out for a serious overhaul... C is it!

    If you are going to be critical, be critical of people who choose to force others to use obsolete products when more modern and effective alternatives are readily available. But it would be advisable to abandon your habit of belittling the products themselves or (implicitly) those who created them.
    1) Given where most of this stuff comes from, there is value in informing people they are being taught with obsolete tools.
    2) In case you haven't noticed I've been very vocal about getting better teachers and better tools for over a year now.

    Turbo C is *at best* an anachronism that has become a serious drawback in many people's educations.

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    No more turboc fallout threads please!.
    The OP has plenty of good info in this thread to read and digest without another rambling discussion between the regulars.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  9. #9
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    Lets be real plain... C is *rubbish*... Conceptually it's a graceful, elegant and small language which is highly capable at almost any level of programming... But it's stuck in the 70s... No *real* strings (not those stupid char[] arrays we play with), No bounds checks, No overflow or underflow checks, no exception handling... Really, if ever there was a truly brilliant concept crying out for a serious overhaul... C is it!
    How do pascal strings handle data which must be longer than 255 characters?

  10. #10
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by whiteflags View Post
    How do pascal strings handle data which must be longer than 255 characters?
    LOL... Did you catch the part about "up to date"?

    The version of Pascal underlying Delphi allowed 64k strings...
    It had C style strings as well, created in arrays like we do...

    But it also had *array bounds checking* that kept things sane.

    You see that's the actual complaint here. C needs to be brought up to modern needs... real strings, run-time checks, structured exception handling, memory management, etc. It's currently the best choice for non-oop style programming... but it could be a lot better.
    Last edited by CommonTater; 10-14-2011 at 12:29 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. alternative to strcat/strncat
    By DampfHans in forum C Programming
    Replies: 4
    Last Post: 12-02-2010, 11:28 AM
  2. Problems with strncat
    By CashCow01 in forum C Programming
    Replies: 8
    Last Post: 03-11-2010, 08:44 AM
  3. strncat..strange behaviour
    By BlackOps in forum C Programming
    Replies: 20
    Last Post: 07-28-2009, 05:32 AM
  4. Pointers and strncat
    By simpatico_qa in forum C Programming
    Replies: 14
    Last Post: 04-27-2009, 02:35 AM
  5. Problem with strncat() function (newbie)
    By Kettch in forum C Programming
    Replies: 2
    Last Post: 12-08-2001, 02:54 AM