Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

farmerdoug

macrumors 6502a
Original poster
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
 
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.
 
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

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.
 
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.

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.
 
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

farmerdoug,

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

You say you're now compiling your code using a C++ compiler?
 
Just declare the destination to be longer than the longest strncpy and bzero the destination before any strncpy.

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.)
 
I don't know why C programmers are willing to put up with such an unsafe language. Why not try Cyclone instead (http://cyclone.thelanguage.org/)?
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. 🙂
 
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

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 );
 
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.
 
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.

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.
 
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.

. . . other words snipped . . .

Thanks for your answer, although I don't care for the condescending tone of your rhetorical question.
 
And a little side note, if you're using UTF-8 then both strncpy and my_strcpy are badly broken.

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.
 
Thanks for your answer, although I don't care for the condescending tone of your rhetorical question.

"I'd be curious to hear your rationale" is what you posted; the reply was matching.

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.

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.
 
"I'd be curious to hear your rationale" is what you posted; the reply was matching.

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.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.