为什么应该使用 strncpy 而不是 strcpy?
编辑:我已经添加了示例的源代码。
我遇到了这个示例:
char source[MAX] = "123456789";
char source1[MAX] = "123456789";
char destination[MAX] = "abcdefg";
char destination1[MAX] = "abcdefg";
char *return_string;
int index = 5;
/* This is how strcpy works */
printf("destination is originally = '%s'\n", destination);
return_string = strcpy(destination, source);
printf("after strcpy, dest becomes '%s'\n\n", destination);
/* This is how strncpy works */
printf( "destination1 is originally = '%s'\n", destination1 );
return_string = strncpy( destination1, source1, index );
printf( "After strncpy, destination1 becomes '%s'\n", destination1 );
产生了这个输出:
destination is originally = 'abcdefg' After strcpy, destination becomes '123456789' destination1 is originally = 'abcdefg' After strncpy, destination1 becomes '12345fg'
这让我想知道为什么有人会想要这种效果。 看起来会很混乱。 这个程序让我觉得你基本上可以用 Tom Bro763 复制某人的名字(例如 Tom Brokaw)。
使用 strncpy()
相对于 strcpy()
有什么优点?
Edit: I've added the source for the example.
I came across this example:
char source[MAX] = "123456789";
char source1[MAX] = "123456789";
char destination[MAX] = "abcdefg";
char destination1[MAX] = "abcdefg";
char *return_string;
int index = 5;
/* This is how strcpy works */
printf("destination is originally = '%s'\n", destination);
return_string = strcpy(destination, source);
printf("after strcpy, dest becomes '%s'\n\n", destination);
/* This is how strncpy works */
printf( "destination1 is originally = '%s'\n", destination1 );
return_string = strncpy( destination1, source1, index );
printf( "After strncpy, destination1 becomes '%s'\n", destination1 );
Which produced this output:
destination is originally = 'abcdefg' After strcpy, destination becomes '123456789' destination1 is originally = 'abcdefg' After strncpy, destination1 becomes '12345fg'
Which makes me wonder why anyone would want this effect. It looks like it would be confusing. This program makes me think you could basically copy over someone's name (eg. Tom Brokaw) with Tom Bro763.
What are the advantages of using strncpy()
over strcpy()
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
strncpy()
函数在设计时考虑了一个非常特殊的问题:操作以原始 UNIX 目录条目的方式存储的字符串。 它们使用一个短的固定大小的数组(14 字节),并且仅当文件名比数组短时才使用 null 终止符。这就是
strncpy()
的两个奇怪之处:对于“更安全的
strcpy()
”,您最好使用strncat()
,如下所示:这将始终终止结果,并且不会复制超过必要的。
The
strncpy()
function was designed with a very particular problem in mind: manipulating strings stored in the manner of original UNIX directory entries. These used a short fixed-sized array (14 bytes), and a nul-terminator was only used if the filename was shorter than the array.That's what's behind the two oddities of
strncpy()
:For a "safer
strcpy()
", you are better off usingstrncat()
like so:That will always nul-terminate the result, and won't copy more than necessary.
虽然我知道
strncpy
背后的意图,但它并不是一个真正好的函数。 两者都避免。 雷蒙德·陈 (Raymond Chen) 解释。另请参阅为什么 strncpy 不安全?
While I know the intent behind
strncpy
, it is not really a good function. Avoid both. Raymond Chen explains.See also Why is strncpy insecure?
strncpy
通过要求您在其中输入长度来防止缓冲区溢出。strcpy
取决于尾随\0
,这可能并不总是发生。其次,为什么你选择只复制 7 个字符串上的 5 个字符超出了我的范围,但它产生了预期的行为。 它仅复制前 n 个字符,其中 n 是第三个参数。
n
函数全部用作针对缓冲区溢出的防御性编码。 请使用它们代替旧函数,例如strcpy
。strncpy
combats buffer overflow by requiring you to put a length in it.strcpy
depends on a trailing\0
, which may not always occur.Secondly, why you chose to only copy 5 characters on 7 character string is beyond me, but it's producing expected behavior. It's only copying over the first
n
characters, wheren
is the third argument.The
n
functions are all used as defensive coding against buffer overflows. Please use them in lieu of older functions, such asstrcpy
.strncpy 并不比 strcpy 更安全,它只是将一种类型的错误与另一种类型的错误进行交换。 在 C 中,处理 C 字符串时,您需要知道缓冲区的大小,这是没有办法解决的。 strncpy 对于其他人提到的目录是合理的,但除此之外,你永远不应该使用它:
strncpy is NOT safer than strcpy, it just trades one type of bugs with another. In C, when handling C strings, you need to know the size of your buffers, there is no way around it. strncpy was justified for the directory thing mentioned by others, but otherwise, you should never use it:
strncpy()
函数是更安全的函数:您必须传递目标缓冲区可以接受的最大长度。 否则,可能会发生源字符串未正确以 0 结尾的情况,在这种情况下,strcpy() 函数可能会将更多字符写入目标,从而破坏目标缓冲区之后内存中的任何内容。 这是许多漏洞利用中使用的缓冲区溢出问题。此外,对于像 read() 这样的 POSIX API 函数,它不会将终止 0 放入缓冲区,而是返回读取的字节数,您可以手动输入 0,或使用
strncpy()
复制它。在您的示例代码中,
index
实际上不是索引,而是一个count
- 它告诉最多从源复制到目标的字符数。 如果source的前n个字节中没有空字节,则放置在destination中的字符串不会以空结尾The
strncpy()
function is the safer one: you have to pass the maximum length the destination buffer can accept. Otherwise it could happen that the source string is not correctly 0 terminated, in which case thestrcpy()
function could write more characters to destination, corrupting anything which is in the memory after the destination buffer. This is the buffer-overrun problem used in many exploitsAlso for POSIX API functions like
read()
which does not put the terminating 0 in the buffer, but returns the number of bytes read, you will either manually put the 0, or copy it usingstrncpy()
.In your example code,
index
is actually not an index, but acount
- it tells how many characters at most to copy from source to destination. If there is no null byte among the first n bytes of source, the string placed in destination will not be null terminated您正在寻找的是函数
strlcpy()
,它总是以 0 终止字符串并初始化缓冲区。 它还能够检测溢出。 唯一的问题是,它不是(真正)可移植的,并且仅存在于某些系统(BSD、Solaris)上。 这个函数的问题在于它打开了另一个蠕虫罐头,正如关于http://en.wikipedia.org/wiki/Strlcpy
我个人的观点是,它很大程度上比
strncpy()
和strcpy()
更有用。 它具有更好的性能,是snprintf()
的良好伴侣。 对于没有它的平台来说,实现起来相对容易。(对于应用程序的开发阶段,我将这两个函数(
snprintf()
和strlcpy()
)替换为陷阱版本,该版本会在缓冲区溢出或截断时残酷中止程序.这可以快速捕获最严重的违规者,特别是如果您使用其他人的代码库,则可以轻松实现:
What you're looking for is the function
strlcpy()
which does terminate always the string with 0 and initializes the buffer. It also is able to detect overflows. Only problem, it's not (really) portable and is present only on some systems (BSD, Solaris). The problem with this function is that it opens another can of worms as can be seen by the discussions onhttp://en.wikipedia.org/wiki/Strlcpy
My personal opinion is that it is vastly more useful than
strncpy()
andstrcpy()
. It has better performance and is a good companion tosnprintf()
. For platforms which do not have it, it is relatively easy to implement.(for the developement phase of a application I substitute these two function (
snprintf()
andstrlcpy()
) with a trapping version which aborts brutally the program on buffer overflows or truncations. This allows to catch quickly the worst offenders. Especially if you work on a codebase from someone else.EDIT:
strlcpy()
can be implemented easily:对我来说,将字符串复制到另一个字符串并在达到目的地限制时停止的最干净的方法是 snprintf
输出:
但可能不是最有效的。
更新
实际上我们可以直接使用sprintf特殊修饰符
%.*s
,这需要一个附加参数(放在要复制的参数字符串之前),它指定要复制的最大字符数。输出:
For me the most clean way to copy a string into another and stop if you reach the destination's limit is snprintf
Outputs:
But maybe not the most efficient.
Update
Actually we may directly use sprintf with the special modifier
%.*s
, this expects an additional argument (put before the argument string to copy) which specifies the maximum number of characters to copy.Outputs:
strncpy 使用 '\0' 来填充目标的源大小,即使目标的大小较小......
联机帮助页:
strncpy fills the destination up with '\0' for the size of source, eventhough the size of the destination is smaller....
manpage:
这可以用在许多其他场景中,在这些场景中,您只需将原始字符串的一部分复制到目标。 使用 strncpy() 可以复制原始字符串的有限部分,这与 strcpy() 不同。 我看到您提供的代码来自 publib.boulder.ibm.com。
This may be used in many other scenarios, where you need to copy only a portion of your original string to the destination. Using strncpy() you can copy a limited portion of the original string as opposed by strcpy(). I see the code you have put up comes from publib.boulder.ibm.com.
这取决于我们的要求。
对于 Windows 用户
每当我们不想复制整个字符串或只想复制 n 个字符时,我们就使用 strncpy。 但 strcpy 复制整个字符串,包括终止空字符。
这些链接将帮助您更多地了解 strcpy 和 strncpy
以及我们可以在哪里使用。
关于 strcpy
关于 strncpy
That depends on our requirement.
For windows users
We use strncpy whenever we don't want to copy entire string or we want to copy only n number of characters. But strcpy copies the entire string including terminating null character.
These links will help you more to know about strcpy and strncpy
and where we can use.
about strcpy
about strncpy
strncpy 是 strcpy 的更安全版本,事实上您永远不应该使用 strcpy,因为它潜在的缓冲区溢出漏洞使您的系统容易受到各种攻击
the strncpy is a safer version of strcpy as a matter of fact you should never use strcpy because its potential buffer overflow vulnerability which makes you system vulnerable to all sort of attacks