On 2023-11-10 11:52, Alejandro Colomar wrote:
Do you have any numbers?
It depends on size of course. With programs like 'tar' (one of the few programs that actually needs something like strncpy) the destination buffer is usually fairly small (32 bytes or less) though some of them are 100 bytes. I used 16 bytes in the following shell transcript:
$ for i in strnlen+strcpy strnlen+memcpy strncpy stpncpy strlcpy; do echo; echo $i:; time ./a.out 16 100000000 abcdefghijk $i; done
strnlen+strcpy: real 0m0.411s user 0m0.411s sys 0m0.000s strnlen+memcpy: real 0m0.392s user 0m0.388s sys 0m0.004s strncpy: real 0m0.300s user 0m0.300s sys 0m0.000s stpncpy: real 0m0.326s user 0m0.326s sys 0m0.000s strlcpy: real 0m0.623s user 0m0.623s sys 0m0.000s... where a.out was generated by compiling the attached program with gcc -O2 on Ubuntu 23.10 64-bit on a Xeon W-1350.
I wouldn't take these numbers all that seriously, as microbenchmarks like these are not that informative these days. Still, for a typical case one should not assume strncpy must be slower merely because it has more work to do; quite the contrary.
#include <stdlib.h> #include <string.h> int main (int argc, char **argv) { if (argc != 5) return 2; long bufsize = atol (argv[1]); char *buf = malloc (bufsize); long n = atol (argv[2]); char const *a = argv[3]; if (strcmp (argv[4], "strnlen+strcpy") == 0) { for (long i = 0; i < n; i++) { if (strnlen (a, bufsize) == bufsize) return 1; strcpy (buf, a); } } else if (strcmp (argv[4], "strnlen+memcpy") == 0) { for (long i = 0; i < n; i++) { size_t alen = strnlen (a, bufsize); if (alen == bufsize) return 1; memcpy (buf, a, alen + 1); } } else if (strcmp (argv[4], "strncpy") == 0) { for (long i = 0; i < n; i++) if (strncpy (buf, a, bufsize)[bufsize - 1]) return 1; } else if (strcmp (argv[4], "stpncpy") == 0) { for (long i = 0; i < n; i++) if (stpncpy (buf, a, bufsize) == buf + bufsize) return 1; } else if (strcmp (argv[4], "strlcpy") == 0) { for (long i = 0; i < n; i++) if (strlcpy (buf, a, bufsize) == bufsize) return 1; } else return 2; }