Thread: strcpy get errors

  1. #46
    Ultraviolence Connoisseur
    Join Date
    Mar 2004
    Posts
    555
    I think that that is bad advice in this case -> Think about this example
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
     
    #define STR_MAX 16
     
     
    int main(void)
    {
        char a[]="Giovani";
        char b[]="Loserone+_+";
     
        strcpy(a,b);
    ...
    Again, I have to disagree with you there. While I'll agree that both methods may have drawbacks, lets see which error is easier to spot:
    Code:
    /* You can visually see that b is longer then a */
    char a[] = "Some string here";
    char b[] = "Some longer string here";
    ...
    strcpy(a, b);
    vs.

    Code:
    char a[16] = "some string here";
    char b[16] = "some other string";
    ...
    strcpy(a, b);
    When you see an array declared with a set size, you assume that the coder knew the correct size, you're not going to manually count the length of the string and ensure there is enough space for the literal they are initializing with. Above the first string a[] has ALMOST enough space, except for the trailing NULL which is an extremely easy mistake to make. Not to mention b[] is off by about 3-4 chars (but can you tell that instantly, by visually looking at it?)

  2. #47
    Registered User
    Join Date
    Nov 2012
    Posts
    1,393
    Quote Originally Posted by nonpuz View Post
    Code:
    char a[16] = "some string here";
    char b[16] = "some other string";
    ...
    strcpy(a, b);
    When you see an array declared with a set size, you assume that the coder knew the correct size
    The problem is that C allows initializing non-null terminated string constants, probably for historical reasons. For maintainable string constants which are null-terminated but also have a fixed buffer size, try the following notation instead:

    Code:
    char a[LEN] = "some string here\0";
    char b[LEN] = "some other string\0";
    ...
    strncpy(a, b, LEN);
    If your maintainers change the strings later, they must follow the rule of keeping the \0 at the end. In the worst case, you must update LEN to be one byte longer than necessary, but your static variables a and b will always be null-terminated.

  3. #48
    Fountain of knowledge.
    Join Date
    May 2006
    Posts
    794
    Quote Originally Posted by Click_here View Post
    That's like saying, "I won't build a house strong enough for an Earthquake, because it may get hit with a comet".

    However we only build houses strong enough to for an earthquake in earthquake zones!!!

  4. #49
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by esbo
    However we only build houses strong enough to for an earthquake in earthquake zones!!!
    If you want to use "earthquake zone" as an analogy for "user input", then earthquake zones are almost everywhere. The only places where there is no earthquake zone is when you can guarantee that the input will not result in buffer overflow, but in practice that means that you are only programming for yourself or for some very special scenario, e.g., a programming contest for which test input is guaranteed to be correct.

    The core problem is that gets cannot be rendered safe. You can only assume that the input will not result in buffer overflow, and this is almost always a bad assumption. Hence, the good practice is to avoid gets. Use it at your own peril, and you will be slammed for suggesting it to others here.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #50
    Stoned Witch Barney McGrew's Avatar
    Join Date
    Oct 2012
    Location
    astaylea
    Posts
    420
    gets is only as unsafe as strcpy is, in that it will mess up if it's used incorrectly. If you can't guarantee that it will read a newline before it exhausts the buffer (which is probably the case 99.5% of the time it's used), then your program is effectively broken and you should rewrite it. On the other hand, if you can make that guarantee (see ungetc), then it's just as safe as using strcpy when you can guarantee that the destination buffer is sufficiently large for the source string. Although, if you happen to find yourself in the rare situation where gets is useful and can be used safely, you should still avoid it since it's no longer part of the standard C library (although this isn't an issue if your code complies strictly with an older revision of the standard.) If you're just reading lines of input from the user into a buffer (where you can make no guarantee about what is read from the stream), then it's one of the worst ways to go about it as it seems to work well for lines less than the destination buffer size, but breaks horribly with lines that exceed it.

    As for the issue with explicitly defining the size of arrays that are defined with string literals, it depends on the situation. It's only useful where you know that it will need to store a string larger than the one it's initialised with. You can always verify the size of the object using sizeof, so there isn't really any point in doing “char a[4] = "abc"”, for example, because if you decide to initialise it with another string later on, then you need to recalculate its size manually, which defeats the purpose of omitting the size and letting the implementation calculate it.

  6. #51
    Fountain of knowledge.
    Join Date
    May 2006
    Posts
    794
    Quote Originally Posted by laserlight View Post
    If you want to use "earthquake zone" as an analogy for "user input", then earthquake zones are almost everywhere. The only places where there is no earthquake zone is when you can guarantee that the input will not result in buffer overflow, but in practice that means that you are only programming for yourself or for some very special scenario, e.g., a programming contest for which test input is guaranteed to be correct.

    The core problem is that gets cannot be rendered safe. You can only assume that the input will not result in buffer overflow, and this is almost always a bad assumption. Hence, the good practice is to avoid gets. Use it at your own peril, and you will be slammed for suggesting it to others here.
    I am not suggesting it to others, I just do not make pointless work for myself just for the sake of it.
    If I am just doing some small test program for my self I do not treat it is as if I was working on a major defence project.
    the idea that I should get into the practice of doing that just in case I ever do seem pretty ridiculous to me.
    I am capable of thinking for myself.

  7. #52
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    Strncpy is your best bet with a definition for the maximum string length.

    If you wanted to have a faster program, define the strings and separate pointers to point to them and then change where they point to.

    the idea that I should get into practice of doing that just in case I ever do seem ridiculous to me
    You're right - Practicing something to get good at it is for suckers!
    Fact - Beethoven wrote his first symphony in C

  8. #53
    Stoned Witch Barney McGrew's Avatar
    Join Date
    Oct 2012
    Location
    astaylea
    Posts
    420
    I just do not make pointless work for myself just for the sake of it.
    Then why introduce bugs into your programs?

    the idea that I should get into the practice of doing that just in case I ever do seem pretty ridiculous to me.
    It has nothing to do with defense, it's about writing programs that work in a predictable manner. The moment you access memory that you haven't allocated is the moment the behaviour of your program becomes unpredictable.

    Also, if it crashes because of a fire then it's not the fault of the program, it's the fault of the fire. However, it is the fault of the program if it crashes because it tries to copy a character into an invalid memory location.

  9. #54
    Registered User
    Join Date
    Nov 2012
    Posts
    1,393
    Quote Originally Posted by esbo View Post
    I am not suggesting it to others, I just do not make pointless work for myself just for the sake of it.
    If I am just doing some small test program for my self I do not treat it is as if I was working on a major defence project.
    Wow. fgets requires 3 parameters and gets requires 1. Is typing two more parameters really that much extra work? Write a macro if it really helps you.

    Basically the choice comes down to between "fast code" or "good code". There is a helpful illustration here to describe how this development process works:

    xkcd: Good Code

  10. #55
    Fountain of knowledge.
    Join Date
    May 2006
    Posts
    794
    Quote Originally Posted by c99tutorial View Post
    Wow. fgets requires 3 parameters and gets requires 1. Is typing two more parameters really that much extra work? Write a macro if it really helps you.

    Basically the choice comes down to between "fast code" or "good code". There is a helpful illustration here to describe how this development process works:

    xkcd: Good Code
    Yes!! It really is two much work!!
    it is three time the amount of work!!

    So if I follow your rules I will be 3 times less productive - so no thanks I am happy doing it my way.
    I don't want to write a MACRO, that takes time too, what if there is a bug in the MACRO.

    I mean given I have just wrote the program the chance of me over flowing the buff I specified are slim, indeed to all extent and purposes zero.

    So why do 3 times the work for zero benefit? Does not make sense to me. That time could be used more productively elsewhere.

  11. #56
    Fountain of knowledge.
    Join Date
    May 2006
    Posts
    794
    Quote Originally Posted by Barney McGrew View Post
    Then why introduce bugs into your programs?


    It has nothing to do with defense, it's about writing programs that work in a predictable manner. The moment you access memory that you haven't allocated is the moment the behaviour of your program becomes unpredictable.

    Also, if it crashes because of a fire then it's not the fault of the program, it's the fault of the fire. However, it is the fault of the program if it crashes because it tries to copy a character into an invalid memory location.
    It's not going to crash though is it? I am not going to declare a small buffer and then over fill it.
    Even if I did he cause of the crash would be obvious.

  12. #57
    Registered User
    Join Date
    Nov 2012
    Posts
    1,393
    OK so if you really want here's the GETS macro to behave like gets but in a somewhat safe way:

    Code:
    #define GETS(buf) do { \
         _Static_assert(sizeof buf > sizeof(void*), "GETS(buf): character array required"); \
        fgets(buf, sizeof(buf), stdin); \
         if (buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0'; \
    } while(0)
    Usage:
    Code:
    printf("type some foo: ");
    char line[20];
    GETS(line);
    printf("your foo was: %s\n", line);
    Last edited by c99tutorial; 01-16-2013 at 05:36 PM.

  13. #58
    Stoned Witch Barney McGrew's Avatar
    Join Date
    Oct 2012
    Location
    astaylea
    Posts
    420
    It's not going to crash though is it?
    It may. C doesn't specify what happens when you access such memory.

    I am not going to declare a small buffer and then over fill it.
    What do you consider small? FILE streams are designed to handle huge amounts of data, unlike arrays which is what you're writing into.

    Even if I did he cause of the crash would be obvious.
    It depends. Perhaps you're using an environment that tells you the identifier of the pointer you passed, as well as the name of the function that used it. In my experience, though, you'll usually just observe that your program stopped running and see “Segmentation fault”.
    Last edited by Barney McGrew; 01-16-2013 at 05:40 PM. Reason: Fixed a grammatical error

  14. #59
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by Barney McGrew View Post
    gets is only as unsafe as strcpy is, in that it will mess up if it's used incorrectly. If you can't guarantee that it will read a newline before it exhausts the buffer (which is probably the case 99.5% of the time it's used), then your program is effectively broken and you should rewrite it.
    The reason that folks advocate fgets() over gets() is that there is no way to prevent a user entering enough characters on a line to overrun the buffer. In other words, it is impossible to "make that guarantee".

    Quote Originally Posted by Barney McGrew View Post
    On the other hand, if you can make that guarantee (see ungetc), then it's just as safe as using strcpy when you can guarantee that the destination buffer is sufficiently large for the source string.
    ungetc() does not provide any means to "make that guarantee" when using gets().

    While I note that you are caveating everything you say on the basis of ability to "make that guarantee" in order to argue that gets() is just as safe as strcpy(), your argument is specious. The difference is that the programmer has no way of making that guarantee, as the user can do things which violate it, in a manner that a programmer cannot control (at least, cannot control in code).

    While strcpy() has its flaws, there are reliable techniques the programmer can use in code to avoid those flaws. The number of such reliable techniques available to the programmer when using gets() is exactly zero.

    Quote Originally Posted by Barney McGrew View Post
    Although, if you happen to find yourself in the rare situation where gets is useful and can be used safely, you should still avoid it since it's no longer part of the standard C library (although this isn't an issue if your code complies strictly with an older revision of the standard.)
    The rare situation is not something that can be achieved by a programmer in code. It is when the programmer can physically restrain the user of the program, and prevent them from overrunning the buffer. Very few users would be interested in using a program if they could only do so in the physical presence of the programmer. Very few programmers, even if they were able to physically restrain the user, would have enough persistence to "make that guarantee".

    Also, gets() is still in the C standard. It is deprecated - which means it is scheduled for removal from a future version of the C standard. That is a strong suggestion by the Standard committee that gets() should not be used. It does not mean it is no longer part of the standard ..... yet.
    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.

  15. #60
    Stoned Witch Barney McGrew's Avatar
    Join Date
    Oct 2012
    Location
    astaylea
    Posts
    420
    The number of such reliable techniques available to the programmer when using gets() is exactly zero.
    Do you see any potential errors here?
    Code:
    char c;
    if (ungetc('\n', stdin) != EOF)
            gets(&c);
    Also, gets() is still in the C standard. It is deprecated - which means it is scheduled for removal from a future version of the C standard.
    I don't know about this. If you look at the outline of major changes in n1570.pdf, you'll see this:

    — removed the gets function (<stdio.h>)
    Last edited by Barney McGrew; 01-16-2013 at 06:05 PM. Reason: Fixed a quote

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Help using strcpy
    By laxkrzy in forum C Programming
    Replies: 1
    Last Post: 11-15-2010, 11:09 PM
  2. Replies: 1
    Last Post: 06-19-2010, 07:42 AM
  3. What's up with this strcpy?
    By fanoliv in forum C Programming
    Replies: 7
    Last Post: 06-19-2006, 05:24 PM
  4. strcpy
    By Tibo in forum C Programming
    Replies: 2
    Last Post: 03-27-2003, 07:02 AM
  5. strcpy
    By Unregistered in forum C++ Programming
    Replies: 6
    Last Post: 08-01-2002, 01:39 PM