Chinaunix首页 | 论坛 | 博客
  • 博客访问: 818637
  • 博文数量: 756
  • 博客积分: 40000
  • 博客等级: 大将
  • 技术积分: 4980
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-13 14:40
文章分类

全部博文(756)

文章存档

2011年(1)

2008年(755)

我的朋友

分类:

2008-10-13 16:10:37

作者: 2007年12月28日

先看代码:

 char buf [20];
strcpy(buf, "abcdefghijklmnopqrstuvwxyz");

呵呵,只有两行,单独看都没错,合起来就麻烦了。
是的,buf的长度只有20字节,无法容纳一个26字符还要外带一个'\0'结尾的字符串。
这个拷贝操作将导致内存写操作越界,从而破坏其他地方的数据。

这并不是一个很难发现的错误,但是当buf的定义和拷贝的时机相隔很远,或者频繁使用了strcat一类函数而忽视了字符串长度的时候,想要找出这个问题,还是比较麻烦的。

解决方法有几种,最简单的就是定义足够大的缓冲区,比如当拷贝路径的时候,使用MAX_PATH宏。但是这有时候不太现实。
我们也可以使用一个string类来管理,比如MFC的CString,或者STL的std::string,都可以,当增长的时候只要调用operator +就可以了。
还有一个方式是使用strncpy,强制每次拷贝都输入一个长度参数。当然,这个参数的数值一般是buf的长度减1,buf的最后一个字节,则在初始化的时候就应该赋值为'\0'。这可以避免很多问题,但是遇到strcat的时候仍旧会有潜在危险,你可以考虑使用strncat,虽然这会带来额外的复杂性。


--------------------next---------------------
1。最大限度的利用内存
如果s[3],则strncpy( s,"abc",sizeof(s) )后s不是 'a' 'b' '\0',而是 'a' 'b' 'c';
如果是s[大于3],则为 'a' 'b' 'c' '\0' ... 。
一个巨大的好处就是它连结尾的\0都算计上了,空间有多余时\0正好指定出结尾位置,空间全用上时那字符串长度当然就是sizeof(s),根本不需要\0来冗余一次。
俺曾有幸看过国外几家XX数据库的代码,皆毫不例外的使用这种方式。因为每个字符串长度都是预先确定下来了,所以不需要使用参数来传递,倒也是有利而无害。
BTW: printf( "%.*s", _countf(s), s ); 或直接 printf( "%.3s", s ); 无论s中有\0还是无\0,都能正确的输出。

2。strncpy第二个作用就是在中间replace了,strcpy不行,它一定会加上\0从而截至掉后面的数据。

3。当然就是你说的东东了:)
--------------------next---------------------

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