C to C++ changes

Discussion in 'Mac Programming' started by farmerdoug, May 26, 2010.

  1. farmerdoug macrumors 6502a

    Joined:
    Sep 16, 2008
    #1
    Code:
    char num[4];
    strncpy(num, files[set]+ len - 16,3);
        strcpy(cmd, "mkdir test/");
        strcat(cmd, num);
        system(cmd);
    
    
    results in a directory called 024_%FF in C++ instead of 024 in C

    huh?
    thanks
     
  2. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    Location:
    Sailing beyond the sunset
    #2
    Read the man page for strncpy(). Note the conditions under which dst will not be terminated by a nul. Consider whether this might be happening due to the unspecified and unpredictable initial contents of your num[4] array, given the len 3 you pass to strncpy().

    Read the man page for strlcpy(). Consider using it instead of strncpy().


    This app simplifies reading man pages:
    http://www.bruji.com/bwana/

    With it installed, enter this command in Terminal:
    Code:
    open man:strncpy
    
    Or in a browser window, enter the URL man:strncpy in the address bar.

    Substitute any command, function, etc. for strncpy and it will show that man page. Or use Bwana's index to show all commands, functions, etc.
     
  3. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #3
    Not a difference between C and C++, but a dangerous bug in your code that relied on undefined behaviour and could have crashed your C code at any time. The array num is initially filled with undefined data. The last byte num [3] _stays_ filled with undefined data.

    Do _NOT_ use strncpy. _NOT EVER_. It is a highly dangerous. People use it to avoid buffer overflows with strcpy without thinking, but in those cases where strcpy would have overflowed a buffer, strncpy leaves a dangerous time bomb in the form of an unterminated string. As you just noticed.
     
  4. farmerdoug thread starter macrumors 6502a

    Joined:
    Sep 16, 2008
  5. jpyc7 macrumors 6502

    Joined:
    Mar 8, 2009
    Location:
    Denver, CO
    #5
    How is one time bomb worse than the other? With strcpy and buffer overflow, you potentially end up with changed variable values (from overwriting other memory). With strncpy and unterminated string, you could potentially go into some infinite loop if you try to do something with the string later.

    I don't see how one can determine which has worse effects, but I'd be curious to hear your rationale.
     
  6. lloyddean macrumors 6502a

    Joined:
    May 10, 2009
    Location:
    Des Moines, WA
    #6
    farmerdoug,

    Would you mind telling me what 'files', 'set' and 'len' are?

    You say you're now compiling your code using a C++ compiler?
     
  7. firewood macrumors 604

    Joined:
    Jul 29, 2003
    Location:
    Silicon Valley
    #7
    Just declare the destination to be longer than the longest strncpy and bzero the destination before any strncpy.
     
  8. Cromulent macrumors 603

    Cromulent

    Joined:
    Oct 2, 2006
    Location:
    The Land of Hope and Glory
    #8
    I was under the impression bzero was deprecated in the latest POSIX?
     
  9. Sander macrumors 6502

    Joined:
    Apr 24, 2008
    #9
    The latter is not necessary. strncpy() will fill the remaining space with '\0'. (Weird, but true - probably a remnant from something which once came in handy while implementing Unix.)
     
  10. Bill McEnaney macrumors 6502

    Joined:
    Apr 29, 2010
    #10
  11. qtx43 macrumors 6502a

    Joined:
    Aug 4, 2007
    #11
    Because life on the edge is the only life worth living. And because, you know, C is probably on more platforms and has more legacy libraries than any other language (I'm just guessing), and defines the defacto standard calling convention for libraries, and is relatively simple to learn (albeit with lots of gotchas for the unwary), and is reasonably efficient for low level code. And it isn't a niche language that almost nobody else uses; As wonderful as Cyclone may be, you're not going to get everyone to suddenly decide that that is the one language everybody needs to start using. Way too much competition for that spot. If you're asking why C got to be that way: it was pretty darn good for it's time, and still is actually.

    Probably the biggest thing is the library binary format. The C standards committee is very conservative about ensuring compatibility.

    Or maybe you're just asking a rhetorical question out of frustration. In which case: nevermind. :)
     
  12. philips macrumors regular

    philips

    Joined:
    Oct 14, 2004
    Location:
    Baden-Württemberg, Germany
    #12
    Others have already said: do NOT use strncpy.

    In my brains it should be something like that, provided that "cmd" is declared like e.g. "char cmd[MAX_PATH]":

    Code:
        snprintf( cmd, sizeof(cmd), "mkdir test/%.*s", 3, &(files[set][len]) );
        system( cmd );
    
     
  13. subsonix macrumors 68040

    Joined:
    Feb 2, 2008
    #13
    strcpy is better, as something like:

    Code:
    strncpy(string1, string2, strlen(string2));
    will copy everything except the null terminating character, which is what happend in the first post. The string supposed to be 024, but only 3 characters was copied.

    Mac os also includes strlcpy from OpenBSD, which copies n bytes -1 and null terminates the string.
     
  14. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #14
    Done any serious software development recently?

    When you have bugs in your software, you want bugs that are blatantly obvious so that you detect them in development, and don't wait until the customers detect them. strcpy trying to copy too much data has a much better chance of crashing your program in development, so you find the bug and fix it. strncpy limits the damage to the tiniest amount possible, so there is a much higher chance that the bug escapes from development to customers.

    However, I wasn't comparing strcpy and strncpy - I was criticising strncpy on its own. The design of that function is completely brain-damaged. If you want to prevent buffer overflows, a very simple function will do:

    Code:
    void my_strcpy (char* dst, const char* src, size_t dest_size)
    {
        if (strlen (src) < dest_size) {
            strcpy (dst, src);
        } else if (dest_size > 0) {
            memcpy (dst, src, dest_size - 1);
            dst [dest_size - 1] = '\0';
            assert (0 && "my_strcpy: src string too long");
        } else {
            assert (0 && "my_strcpy: dest_size == 0");
        }
    }
    
    This avoids the stupidity of strncpy, which leaves you with an undelimited string which will cause trouble later on, and it will tell you during development if the situation happens.

    HOWEVER this is only putting a band aid on a programming bug. Either the destination buffer size was too small, or the string length is not limited, so you should dynamically allocate a string. And C++ with std::string is your friend here. And a little side note, if you're using UTF-8 then both strncpy and my_strcpy are badly broken.
     
  15. jpyc7 macrumors 6502

    Joined:
    Mar 8, 2009
    Location:
    Denver, CO
    #15
    Thanks for your answer, although I don't care for the condescending tone of your rhetorical question.
     
  16. Sander macrumors 6502

    Joined:
    Apr 24, 2008
    #16
    Why..? AFAIK, UTF-8 promises not to insert any spurious 0 characters. Remember that strlen(some_utf8_string) still returns the number of chars in that string, not the number of characters.

    I agree with your assessment of the strangeness of strncpy() though:

    - It (silently) doesn't null-terminate if there isn't any room
    - It fills the entrire rest of the destination with null characters if there is room, instead of appending a single null character.

    I'm hesitant to call things related to C "brain-dead" though, as I'm sure the people who first came up with strncpy() were much smarter than me.
     
  17. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #17
    "I'd be curious to hear your rationale" is what you posted; the reply was matching.

    In UTF-8, a code point consists of 1 to 4 bytes or chars. If you try to truncate a UTF-8 string, you _must_ make sure that only whole code points are removed. You can't just cut off; if the first byte that you remove is the second, third or fourth byte of a character then you _must_ remove the other bytes as well. For example, core foundation functions that convert UTF-8 to a CFStringRef or NSString* will fail if a string ends with an incomplete code point.
     
  18. jpyc7 macrumors 6502

    Joined:
    Mar 8, 2009
    Location:
    Denver, CO
    #18
    Well, I meant to strike a skeptical tone, and I'm sorry if you thought I was being condescending. At least in real life, when I am skeptical of what people say, they don't seem to be offended. Of course, I don't do that so much with people I don't know.
     

Share This Page