strncpy or strlcpy in my case
what should I use when I want to copy src_str
to dst_arr
and why?
char dst_arr[10];
char *src_str = "hello";
PS: my head is spinning faster than the disk of my compu开发者_如何学Goter after reading a lot of things on how good or bad is strncpy
and strlcpy
.
Note: I know strlcpy
is not available everywhere. That is not the concern here.
strncpy
is never the right answer when your destination string is zero-terminated. strncpy
is a function intended to be used with non-terminated fixed-width strings. More precisely, its purpose is to convert a zero-terminated string to a non-terminated fixed-width string (by copying). In other words, strncpy
is not meaningfully applicable here.
The real choice you have here is between strlcpy
and plain strcpy
.
When you want to perform "safe" (i.e. potentially truncated) copying to dst_arr
, the proper function to use is strlcpy
.
As for dst_ptr
... There's no such thing as "copy to dst_ptr
". You can copy to memory pointed by dst_ptr
, but first you have to make sure it points somewhere and allocate that memory. There are many different ways to do it.
For example, you can just make dst_ptr
to point to dst_arr
, in which case the answer is the same as in the previous case - strlcpy
.
Or you can allocate the memory using malloc
. If the amount of memory you allocated is guaranteed to be enough for the string (i.e. at least strlen(src_str) + 1
bytes is allocated), then you can use the plain strcpy
or even memcpy
to copy the string. There's no need and no reason to use strlcpy
in this case , although some people might prefer using it, since it somehow gives them the feeling of extra safety.
If you intentionally allocate less memory (i.e. you want your string to get truncated), then strlcpy
becomes the right function to use.
strlcpy()
is safer than strncpy()
so you might as well use it.
Systems that don't have it will often have a s_strncpy()
that does the same thing.
Note : you can't copy anything to dst_ptr
until it points to something
I did not know of strlcpy. I just found here that:
The strlcpy() and strlcat() functions copy and concatenate strings respectively. They are designed to be safer, more consistent, and less error prone replacements for strncpy(3) and strncat(3).
So strlcpy seams safer.
Edit: A full discussion is available here.
Edit2:
I realize that what I wrote above does not answer the "in your case" part of your question. If you understand the limitations of strncpy, I guess you can use it and write good code around it to avoid its pitfalls; but if your are not sure about your understanding of its limits, use strlcpy.
My understanding of the limitations of strncpy and strlcpy is that you can do something very bad with strncpy (buffer overflow), and the worst you can do with strlcpy is to loose one char in the process.
You should always the standard function, which in this case is the C11 strcpy_s()
function. Not strncpy()
, as this is unsafe not guaranteeing zero termination. And not the OpenBSD-only strlcpy()
, as it is also unsafe, and OpenBSD always comes up with it's own inventions, which usually don't make it into any standard.
See http://en.cppreference.com/w/c/string/byte/strcpy
The function strcpy_s is similar to the BSD function strlcpy, except that strlcpy truncates the source string to fit in the destination (which is a security risk)
- strlcpy does not perform all the runtime checks that strcpy_s does
- strlcpy does not make failures obvious by setting the destination to a null string or calling a handler if the call fails.
- Although strcpy_s prohibits truncation due to potential security risks, it's possible to truncate a string using bounds-checked strncpy_s instead.
If your C library doesn't have strcpy_s
, use the safec lib.
https://rurban.github.io/safeclib/doc/safec-3.1/df/d8e/strcpy__s_8c.html
First of all, your dst_ptr has no space allocated and you haven't set it to point at the others, so assigning anything to that would probably cause a segmentation fault.
Strncpy should work perfectly fine - just do:
strncpy(dst_arr, src_str, sizeof(dst_arr));
and you know you wont overflow dst_arr. If you use a bigger src_str you might have to put your own null-terminator at the end of dst_arr, but in this case your source is < your dest, so it will be padded with nulls anyway.
This works everywhere and its safe, so I wouldn't look at anything else unless its intellectual curiousity.
Also note that it would be good to use a non-magic number for the 10 so you know the size of that matches the size of the strncpy :)
you should not use strncpy and not strlcpy for this. Better you use
*dst_arr=0; strncat(dst_arr,src_arr,(sizeof dst_arr)-1);
or without an initialization
sprintf(dst_arr,"%.*s",(sizeof dst_arr)-1,src_arr);
dst_arr here must be an array NOT a pointer.
精彩评论