4 ms·
The advice given in this article is bad. Reducing the length of the copy by one will still fail to null-terminate the string if the source exceeds the destinati
by nneonneo 8y ago
The advice given in this article is bad. Reducing the length of the copy by one will still fail to null-terminate the string if the source exceeds the destination length. You need to add
dst[sizeof(dst)-1] = 0;
or memset the array to zero beforehand. You are not guaranteed to have a zero at the end of the input buffer otherwise (neither local variable arrays nor malloc’d arrays are guaranteed to be zeroed).
strncpy sucks for a second reason: it writes n bytes no matter what the source is. That means if you write
char buffer[16384];
strncpy(buffer, “hello”, sizeof(buffer)-1);
buffer[sizeof(buffer)-1] = 0;
this will fill 16K of memory with zeroes despite only needing to copy a 6-byte string.
strlcpy/strlcat do the right thing (copy up to n-1 bytes and null-terminate); shame they aren’t standardized. In their absence, I suggest snprintf instead:
snprintf(buffer, sizeof(buffer), “%s”, src);
Because snprintf returns the number of bytes that would be written, it can be used to detect overlong input strings, reallocate the buffer as necessary, and also to implement efficient concatenation. It’s also surprisingly fast in most implementations.
- blattimwind 8y ago> The advice given in this article is bad. Thumbing through previous submissions of this domain with discussion, this seems to be a pattern.
- laythea 8y agostrncpy would have to assume that it was working on strings if that were not the case.....oh wait....
- beeforpork 8y agoSame advice everywhere, very good, my words exactly: use snprintf(). But beware of old MS _snprintf: https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2012/2ts7cx93(v=vs.110) https://docs.microsoft.com/en-us/previous-versions/visualstu...
- kdelok 8y agoIs there any reason not to use snprintf for almost every application of string manipulation (aside from strduping)?
- hxchen 8y agoReason: performance. If you just do string manipulation, memncpy is faster. If you need to convert data type, like int to string, then use snprintf.
- nneonneo 8y agoYes, it seems I lied when I said sprintf is surprisingly fast. For most practical purposes it's fine, but if you need to do string manipulation in a hurry, strcpy/strlcpy are going to be faster. See https://gist.github.com/nneonneo/f9dc5c1d1d342d25eae47d56dbad040e https://gist.github.com/nneonneo/f9dc5c1d1d342d25eae47d56dba... for a test harness. On my Mac, with a 16-byte string, 10 million loops: memcpy: 77406 us strlcpy: 101956 us strncpy: 177247 us sprintf: 730819 us snprintf: 699844 us memcpy smokes sprintf - around 10x faster. The vast majority of sprintf's time is spent in setup; for large strings, the gap closes substantially.
- belorn 8y agoIts a shame that many of the solution to those exist as non-standardized calls and seems split between BSD and GNU. Personally I use asprintf quite a lot, and I recall strndup to be quite useful to create a identical copy of a buffer. strndup should have an identical performance to allocating a buffer and then strlcpy, since it too do copy up to n-1 bytes and null-terminate.
- loeg 8y agoIt's a shame they aren't in ISO C, but strdup and strndup are at least standardized by POSIX: http://pubs.opengroup.org/onlinepubs/9699919799/functions/strdup.html http://pubs.opengroup.org/onlinepubs/9699919799/functions/st...
- hxchen 8y agoOr use calloc. It does the same thing as malloc, but init memory to zero automatically.
- tinus_hn 8y agoIf you’re going to allocate the memory you might as well just use the library functions that allocate exactly the space you need and copy the string into it. These tricks are for when you use the stack as an ‘optimization’.
- deleted 8y ago[deleted]