在我的情况下strncpy或strlcpy
当我想将src_str
复制到dst_arr
时,我应该使用什么?为什么?
char dst_arr[10]; char *src_str = "hello";
PS:在阅读了很多关于strncpy
和strlcpy
好坏的事情之后,我的头比我的电脑磁盘旋转得更快。
注意:我知道strlcpy
无处不在。 这不是问题所在。
当目标字符串为零终止时, strncpy
永远不是正确的答案。 strncpy
是一个用于非终止固定宽度字符串的函数。 更确切地说,其目的是将以零结尾的字符串转换为非终止的固定宽度字符串(通过复制)。 换句话说, strncpy
在这里没有意义。
你在这里真正的选择是在strlcpy
和plain strcpy
之间。
当您想要执行“安全”(即可dst_arr
截断)复制到dst_arr
,要使用的正确函数是strlcpy
。
至于dst_ptr
……没有“复制到dst_ptr
”之类的东西。 您可以复制到dst_ptr
指向的dst_ptr
,但首先必须确保它指向某处并分配该内存。 有很多不同的方法可以做到这一点。
例如,你可以让dst_ptr
指向dst_arr
,在这种情况下,答案与前一种情况相同 – strlcpy
。
或者您可以使用malloc
分配内存。 如果你保证分配的内存量足够用于字符串(即至少分配了strlen(src_str) + 1
个字节),那么你可以使用plain strcpy
甚至memcpy
来复制字符串。 在这种情况下没有必要也没有理由使用strlcpy
,虽然有些人可能更喜欢使用它,因为它以某种方式给他们带来额外安全感。
如果你故意分配更少的内存(即你希望你的字符串被截断),那么strlcpy
将成为正确使用的函数。
strlcpy()
比strncpy()
更安全,所以你也可以使用它。
没有它的系统通常会有一个s_strncpy()
来执行相同的操作。
注意 :在指向dst_ptr
之前,您无法将任何内容复制到dst_ptr
我不知道strlcpy。 我刚才在这里找到:
strlcpy()和strlcat()函数分别复制和连接字符串。 它们旨在为strncpy(3)和strncat(3)提供更安全,更一致,更少出错的替代品。
所以strlcpy接缝更安全。
编辑 : 此处提供完整的讨论。
编辑2 :
我意识到我上面写的内容并没有回答你问题的“在你的情况下”部分。 如果您了解 strncpy的局限性,我想您可以使用它并在其周围编写好的代码以避免其陷阱; 但如果您不确定自己对其限制的理解,请使用strlcpy。
我对strncpy和strlcpy的局限性的理解是你可以用strncpy(缓冲区溢出)做一些非常糟糕的事情,而你用strlcpy做的最糟糕的事情就是在这个过程中松掉一个char。
您应始终使用标准函数,在本例中为C11 strcpy_s()
函数。 不是strncpy()
,因为这不安全,不能保证零终止。 而不是OpenBSD-only strlcpy()
,因为它也是不安全的,OpenBSD总是提出它自己的发明,它通常不会成为任何标准。
请参见http://en.cppreference.com/w/c/string/byte/strcpy
函数strcpy_s类似于BSD函数strlcpy,除了strlcpy截断源字符串以适应目标(这是一个安全风险)
- strlcpy不执行strcpy_s执行的所有运行时检查
- 通过将目标设置为空字符串或在调用失败时调用处理程序,strlcpy不会使故障变得明显。
- 虽然strcpy_s禁止因潜在的安全风险而截断,但可以使用bounds-checked strncpy_s来截断字符串。
如果您的C库没有strcpy_s
,请使用safec lib。 https://rurban.github.io/safeclib/doc/safec-3.1/df/d8e/strcpy__s_8c.html
首先,您的dst_ptr没有分配空间,并且您没有将其设置为指向其他空间,因此为此分配任何内容都可能导致分段错误。
Strncpy应该可以正常工作 – 只需:
strncpy(dst_arr, src_str, sizeof(dst_arr));
你知道你不会溢出dst_arr。 如果你使用更大的src_str,你可能必须在dst_arr的末尾放置你自己的null终止符,但是在这种情况下你的源是<你的dest,所以无论如何它都将用空值填充。
这在任何地方都可以使用并且安全,所以除非它的知识性好奇,否则我不会看其他任何东西。
另请注意,为10使用非魔术数字会很好,所以你知道它的大小与strncpy的大小相匹配:)
你不应该使用strncpy而不是strlcpy。 更好用
*dst_arr=0; strncat(dst_arr,src_arr,(sizeof dst_arr)-1);
或者没有初始化
sprintf(dst_arr,"%.*s",(sizeof dst_arr)-1,src_arr);
这里dst_arr必须是一个数组而不是一个指针。