在我的情况下strncpy或strlcpy

时间:2011-08-08 19:04:01

标签: c copy c-strings strncpy

当我想将src_str复制到dst_arr时,我应该使用什么?为什么?

char dst_arr[10];
char *src_str = "hello";

PS:在阅读了很多关于 } strncpy和{{}的内容之后,我的头比我的电脑磁盘旋转得更快1}}。

注意:我知道strlcpy无处不在。这不是问题。

6 个答案:

答案 0 :(得分:28)

当目标字符串为零终止时,

strncpy 永远不会正确答案。 strncpy是一个旨在与非终止固定宽度字符串一起使用的函数。更准确地说,其目的是将以零结尾的字符串转换为非终止的固定宽度字符串(通过复制)。换句话说,strncpy在这里没有任何意义。

您在这里的真正选择是在strlcpy和普通strcpy之间。

如果要执行“安全”(即可能被截断)复制到dst_arr,正确使用的功能是strlcpy

至于dst_ptr ......没有“复制到dst_ptr”之类的东西。您可以复制到dst_ptr指向的内存,但首先必须确保它指向某处并分配该内存。有很多不同的方法可以做到这一点。

例如,您只需将dst_ptr指向dst_arr,在这种情况下,答案与上一个案例中的答案相同 - strlcpy

或者您可以使用malloc分配内存。如果分配的内存量足以保证字符串的足够(即分配了至少strlen(src_str) + 1个字节),那么您可以使用普通strcpy甚至memcpy来复制串。在这种情况下,没有必要也没有理由使用strlcpy,尽管有些人可能更喜欢使用它,因为它以某种方式让他们感到更加安全。

如果你故意分配更少的内存(即你希望你的字符串被截断),那么strlcpy将成为正确使用的函数。

答案 1 :(得分:5)

strlcpy()strncpy()更安全,所以你不妨使用它 没有它的系统通常会有s_strncpy()做同样的事情。

注意:在指向某事之前,您无法将任何内容复制到dst_ptr

答案 2 :(得分:2)

我不知道strlcpy。我刚刚找到了here

  

strlcpy()和strlcat()函数复制和连接字符串   分别。它们旨在更安全,更一致,更安全   strncpy(3)和strncat(3)的更容易出错的替换。

因此接缝更加安全。

修改:可以进行完整的讨论here

<强> EDIT2

我意识到我上面写的内容并没有回答你问题的“在你的情况下”部分。如果您理解 strncpy的限制,我想您可以使用它并在其周围编写好的代码以避免其陷阱;但如果您不确定自己对其限制的理解,请使用strlcpy。

我对strncpy和strlcpy的局限性的理解是你可以用strncpy(缓冲区溢出)做一些非常糟糕的事情,而你用strlcpy做的最糟糕的事情就是在这个过程中松掉一个char。

答案 3 :(得分:1)

您应始终使用标准函数,在本例中为C11 strcpy_s()函数。不是strncpy(),因为这不安全,不能保证零终止。而不仅仅是OpenBSD 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

答案 4 :(得分:-1)

首先,您的dst_ptr没有分配空间,并且您没有将其设置为指向其他空间,因此为此分配任何内容都可能导致分段错误。

Strncpy应该可以正常工作 - 只需:

strncpy(dst_arr, src_str, sizeof(dst_arr));

你知道你不会溢出dst_arr。如果你使用更大的src_str,你可能必须在dst_arr的末尾放置你自己的null-terminator,但是在这种情况下你的源是&lt;你的目标,所以无论如何都会用空值填充。

这在任何地方都可以使用并且安全,所以除非知识分子的好奇,否则我不会看其他任何东西。

另请注意,为10使用非魔术数字会很好,所以你知道它的大小与strncpy的大小匹配:)

答案 5 :(得分:-1)

你不应该使用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这里必须是一个数组而不是一个指针。