4 ms·
>Would you please elaborate on it, and its relevance? Are you referring to N being too high? No, the stack size is implementation-defined anyway. Instead, you
by eMSF 7y ago
>Would you please elaborate on it, and its relevance? Are you referring to N being too high?
No, the stack size is implementation-defined anyway. Instead, you have a classic off-by-one error because you didn't reserve any space for the final null terminator.
Correctly used memccpy would protect against an issue like this, although the destination string would not be correctly terminated, as it's not a safe string function. Also, if your memccpy version had the correct arguments inside the loop, you wouldn't have needed the extra call before the loop to hide the issue, as the memccpy call would have been functionally identical to strcpy except for the last pass of the loop.
>What do you mean exactly? I did observe the results of the buffer. See the printf, or are you not referring to that?
At least in the link you provided, all the printf's that would observe the contents of buf after the loop are commented out. No observable change happens in the execution of the program even if your compiler decides to just remove any calls to strcpy or memccpy.
--
That being said, strcpy is quite efficient at what you're benchmarking; that is, "multiplying" short strings. The task doesn't highlight its shortcomings. (strcpy wouldn't be too bad even if the strings were longer, although memcpy might be slightly faster.)
But consider the following silly example (not checked for errors) that does highlight the issue:
char *next_insert;
size_t remaining_size;
void append_memccpy(const char *str)
{
char *tmp = memccpy(next_insert, str, '\0', remaining_size); // single pass over str
if (tmp) {
--tmp; // move pointer to terminator from one past it
remaining_size -= tmp - next_insert;
next_insert = tmp;
} else { // insufficient size remaining
str += remaining_size; // first remaining_size bytes are already copied
allocate_more();
append_memccpy(str);
}
}
void append_strcpy(const char *str)
{
size_t len = strlen(str); // first pass over str
if (len + 1 < remaining_size) {
strcpy(next_insert, str); // second pass over str
remaining_size -= len;
next_insert += len;
} else {
allocate_more();
append_strcpy(str);
}
}
Now, even though the latter version is extra silly (just to resemble the former more), it doesn't change the fact that with strcpy, we have to process each byte in str twice. If str is long enough, that might not be exactly free.
- johnisgood 7y agoThank you for the reply. I did think about the significance of the length of the string, but I was too lazy to benchmark that. Perhaps another time. Theoretically, for the reasons you mentioned, memccpy should perform better on larger strings, but I am not sure if that really is the case in practice (slow implementation of memccpy, lack of compiler optimizations, etc.), and it seems like that "stick to memccpy" is not an universal rule (obviously). :D
- eMSF 7y agoNote that I mentioned the ordinary memcpy (with a single c) there briefly. memccpy should under no circumstances be faster than strcpy for "string multiplying", as it holds no advantages over it in that use.
- johnisgood 7y agoOuch, my mistake. In any case, could we sum it up? In what cases should memccpy be used over, say, str{n,l}cpy, or even memcpy, and is it in conflict with the article's recommendation or its statement on performance regarding memccpy vs. the alternatives?