Chinaunix首页 | 论坛 | 博客
  • 博客访问: 990936
  • 博文数量: 158
  • 博客积分: 4380
  • 博客等级: 上校
  • 技术积分: 2367
  • 用 户 组: 普通用户
  • 注册时间: 2006-09-21 10:45
文章分类

全部博文(158)

文章存档

2012年(158)

我的朋友

分类: C/C++

2012-11-26 12:48:12

strcpy_s 的 _s 是 safe(安全) 的意思,这个函数是VC特有的,C标准库中自然不会有这种东西。
strcpy_s安全之本意是其在参数中可以指明目标缓冲区的大小,从而避免缓冲区溢出。但:
    对一个合格的程序员,当他可以使用strcpy时,他自然是肯定源串长度小于等于目标区长度的,因为这是strcpy的使用契约。所以strcpy_s除了增加代码量之外(非必要的代码只有增加出错几率这唯一作用),对合格的程序员毫无用户。
    对于一个没在意缓冲区溢出的程序员而言,在避免了“缓冲区溢出”这个错误时,将带来更为严重的bug:
        a. 一个名叫“玻璃玻玻璃”的银行储户来取钱,用strcpy_s“安全”成了“玻璃玻玻”,惨了,这和数据库中的“玻璃玻玻璃”不一致,所以这个储户因为取不到钱而怒气冲冲。
        b. 一个名叫“玻璃玻玻霸”的银行储户来取钱,数据库中有“玻璃玻玻璃”,用strcpy_s“安全”成一样的“玻璃玻玻”,“玻璃玻玻璃”的存款被“玻璃玻玻霸”取走了
        还有另一种情况,就是混乱的设计导致不知道目标缓冲区有多大。这种情况在大型代码中几乎100%存在,在这种情况下,strcpy_s简直成了“掩耳盗铃”。

使用strcpy_s给我的感觉就是“累”,特别的累,根据设计明确不会溢出的时候,也必须填上目标缓冲区大小;而有可能溢出的情况下,又不能简单的不让它不溢出,必须填写一个高级别的bug给设计者。
我想strcpy_s唯一的优点大约就是:对一个初学者而言,这个函数名会提醒你字符串拷贝时要注意目标缓冲区溢出。当然,它不能保证用了它之后目标缓冲区就不溢出,即使能,那得更当心,非本意的数据截断比缓冲区溢出带来的危害更大。



在确定自己需要数据截断时,我更喜欢用strncpy(事实上,我很少用strcpy,大部分都是用strncpy)。
strncpy 和 strcpy_s 的差别在于,后者是拿“s”说事,可惜完全不“s”;而前者是“n”,很多情况下需要。换句话说,差别就是后者名字取错了。(有人会认为这个差别微不足道,我不这么认为,但我不去争论)
但strncpy这个函数的争议很大,因为它有可能不会在目的串后加'\0'。但恰恰这一点则是我喜欢它的原因。
从理论上将,'\0'存在的目的就是标明字符串的有效长度,因此当数据完全填满时,'\0'其实是冗余的,非必要的。在数据库存储等场合中,strncpy非常有用。
char field1[4], field2[4];
strncpy( field1, "ab", 4 );
strncpy( field2, "abcd", 4 );
此时 field1是 'a' 'b' '\0' '\0'
此时 field2是 'a' 'b' 'c' 'd'
printf( "%.*s\n", 4, field1 ); 输出 ab
printf( "%.*s\n", 4, field2 ); 输出 abcd
也就是4个字节被100%利用了,毫无浪费。


假如一定需要'\0'结尾,那么只能将代码改为
char field1[4], field2[4];
strncpy( field1, "ab", 3 )[3] = 0;
strncpy( field2, "abcd", 3 )[3] = 0;
printf( "%s", field1 ); 输出 ab
printf( "%s", field2 ); 输出 abc
不是很直观,所以一定需要'\0'结尾的话,strncpy并不是最好的选择。


strncpy还有一个缺点,他会将余下的字节都赋值成'\0',比如 strncpy( field1, "ab", 4 ); 之后,field1是'a' 'b' '\0' '\0',而不是'a' 'b' '\0' '?'。这对效率而言是一个极大的浪费。

-------------------------------------------------------

回头看,有点跑题了。这个题目是我早想说的,因为bbs上曾有人用了好多年C,却不知道字符串需要以'\0'结尾。问了原因,原来他每次都会先用一个memset,因为数组一直开得很大,所以一直没出问题。
不知道“字符串需要以'\0'结尾”这个根本,那么使用memset也无所裨益。
不知道“缓冲区溢出”这个根本,那么使用xxx_s也无所裨益。

阅读(1598) | 评论(5) | 转发(0) |
给主人留下些什么吧!~~

网友评论2012-11-26 12:49:53

gg
如果别人是做文本处理或者解析的,strncpy那就惨了。这个str是拿来忽悠人的.....这样的函数还是少用比较好,不是人人都那么仔细的strncpy( field1, "ab", 3 )[3] = 0;

网友评论2012-11-26 12:49:43

大虾米(dxm)的技术博客
支持星星 

网友评论2012-11-26 12:49:33

k4
路走多了总会遇到鬼的啦,标准库外的能不用则不用

网友评论2012-11-26 12:49:22

yqever
反正我是从来不用strcpy_s

网友评论2012-11-26 12:49:14

局部变量
坚决拥护星星的观点