2009年(41)
分类: C/C++
2009-04-21 15:58:40
1、strncpy
strncpy有了一个控制复制最大字符的限制,比strcpy要安全一些,但是它依然存在一些bug,在对它的用法不是完全清楚的情况下,稍不注意也会造成溢出。
strncpy说明:
DESCRIPTION The stpcpy() and strcpy() functions copy the string s2 to s1 (including the terminating '\0' character). The strncpy() function copies at most n characters from s2 into s1. If s2 is less than n characters long, the remainder of s1 is filled with `\0' characters. Otherwise, s1 is not terminated. |
注意最后一段,说的是如果源字符串的长度(指strlen长度)大于或等于n,那么s1将不会以'\0'终结。看下面例子:
|
输出:
|
这个例子还看不出会造成什么溢出问题,再看一个例子:
|
输出:
|
看,问题来了!此时s3没有NIL结尾,因此作为作为字符串操作时,有可能会溢出。由此,在使用strncpy时,如果目标缓存的大小小于或等于源字符串的长度时,就要非常注意,千万要手动把末位置为'\0'。
最安全的方法就是:
... |
2、snprintf
在同的平台上snprintf的行为是不一样的。Linux上的版本比较友好,它可以有效的防止溢出,一下是man的说明:
The snprintf() and vsnprintf() functions will write at most n-1 of the characters printed into the output string (the n'th character then gets the terminating `\0'); if the return value is greater than or equal to the n argument, the string was too short and some of the printed characters were discarded. The output is always null-terminated. |
蓝色部分是关键点。假如有以下代码:
|
将不会有任何问题,因为snprintf只向dst写入sizeof(dst) - 1个字符,也就是7个,最有一个字符自动置为'\0'。
然而,这样的代码在win下就会有大问题,代码(win下为_snprintf):
|
输出:
|
为什么会这样呢?因为在win下_snprintf的行为不遵循标准,缓冲区不够大时,它将不会输出结尾的'\0'!
3、strncat
最多从源中拷贝n个字符到目标串中,并在后面加一个0;也就是说,最多会有n+1个字符被写进dest。如果dest的容量为n,那么将会dest将会溢出。看下面代码:
|
输出:
|
由输出可以看出,s2[0]原来是'a',而经过strncat之后,被覆盖成'\0'了!(s2在内存中的开头紧接着s3的末尾)这个例子很好的说明了问题。
4、总结
这几个C标准库的函数从名字上看很相似,但是它们的行为却不是统一的。因此,在使用的时候,一定要搞清楚它们的真正含义(特别是平台不同时),否则很容易出现莫名其妙的错误。
希望此为对你有所帮助。