问题描述
在应用程序中我可以看到很多sprintf
用于复制字符串.
I can see many sprintf
's used in my applications for copying a string.
我有一个字符数组:
char myarray[10];
const char *str = "mystring";
现在,如果我想将字符串str
复制到myarray
,最好使用:
Now if I want want to copy the string str
into myarray
, is is better to use:
sprintf(myarray, "%s", str);
或
strncpy(myarray, str, 8);
?
推荐答案
两者都不用.
-
sprintf
是危险的,已弃用并由snprintf
取代.对字符串输入安全地使用旧的sprintf
的唯一方法是在调用sprintf
之前测量其长度,这很丑陋且容易出错,或者通过添加字段精度说明符(例如%.8s
或%.*s
并带有一个额外的整数参数作为大小限制).这也很丑陋且容易出错,尤其是如果涉及到多个%s
说明符时.
sprintf
is dangerous, deprecated, and superseded bysnprintf
. The only way to use the oldsprintf
safely with string inputs is to either measure their length before callingsprintf
, which is ugly and error-prone, or by adding a field precision specifier (e.g.%.8s
or%.*s
with an extra integer argument for the size limit). This is also ugly and error-prone, especially if more than one%s
specifier is involved.
strncpy
也是危险的.它不是strcpy
的受缓冲区大小限制的版本.这是一个将字符复制到固定长度的,以null- papped (与null- terminated 相反)数组中的函数,其中源可以是C字符串或固定长度的字符数组至少应为目标的大小.它的预期用途是用于固定大小的文本字段的旧版unix目录表,数据库条目等,甚至不想浪费磁盘或内存中的单个字节来进行空终止.可以将它 误用作缓冲区大小受限的strcpy
,但是这样做有两个方面的危害.首先,如果整个缓冲区用于字符串数据(即,如果源字符串的长度至少与dest缓冲区一样长),则它不能使终止终止为空.您可以自己添加终端,但这很丑陋且容易出错.其次,当源字符串短于输出缓冲区时,strncpy
总是用空字节填充整个目标缓冲区.这只是浪费时间.
strncpy
is also dangerous. It is not a buffer-size-limited version of strcpy
. It's a function for copying characters into a fixed-length, null-padded (as opposed to null-terminated) array, where the source may be either a C string or a fixed-length character array at least the size of the destination. Its intended use was for legacy unix directory tables, database entries, etc. that worked with fixed-size text fields and did not want to waste even a single byte on disk or in memory for null termination. It can be misused as a buffer-size-limited strcpy
, but doing so is harmful for two reasons. First of all, it fails to null terminate if the whole buffer is used for string data (i.e. if the source string length is at least as long as the dest buffer). You can add the termination back yourself, but this is ugly and error-prone. And second, strncpy
always pads the full destination buffer with null bytes when the source string is shorter than the output buffer. This is simply a waste of time.
那你应该怎么用呢?
有些人喜欢BSD strlcpy
功能.从语义上讲,它与snprintf(dest, destsize, "%s", source)
相同,除了返回值是size_t
,并且不对字符串长度施加人为的INT_MAX
限制.但是,大多数流行的非BSD系统都缺少strlcpy
,并且编写自己的错误很容易造成危险,因此,如果要使用它,则应从可信赖的来源获得安全,可工作的版本.
Some people like the BSD strlcpy
function. Semantically, it's identical to snprintf(dest, destsize, "%s", source)
except that the return value is size_t
and it does not impose an artificial INT_MAX
limit on string length. However, most popular non-BSD systems lack strlcpy
, and it's easy to make dangerous errors writing your own, so if you want to use it, you should obtain a safe, known-working version from a trustworthy source.
我的偏好是对于任何非平凡的字符串构造仅使用snprintf
,对于已被认为对性能至关重要的一些平凡的情况,仅使用strlen
+ memcpy
.如果您习惯于正确使用此习惯用法,那么几乎不可能意外地编写带有字符串相关漏洞的代码.
My preference is to simply use snprintf
for any nontrivial string construction, and strlen
+memcpy
for some trivial cases that have been measured to be performance-critical. If you get in a habit of using this idiom correctly, it becomes almost impossible to accidentally write code with string-related vulnerabilities.
这篇关于'strncpy'与'sprintf'的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!