用户操作
[留言]  [发消息]  [加为好友] 
订阅我的博客
XML聚合    FeedSky
订阅到鲜果
订阅到Google
订阅到抓虾
lifanxi的公告
<div class="postText"> 欢迎访问我的另一个Blog:<br><a href="http://www.freemindworld.com">www.freemindworld.com</a></div> <!--去掉狗狗--> <script language="javascript"> function removeGougouLogoFromMyBlog(removeFlag) { if(removeFlag) { var tagList = document.getElementsByTagName("A"); var objFound = null; var keyInfoStr = ""; for(var i=0; i<tagList.length; i++) { keyInfoStr = tagList[i].href; if(keyInfoStr.indexOf("gougou.com") >-1 ) { objFound = tagList[i]; objFound.style.display = "none"; } } } } window.setTimeout("removeGougouLogoFromMyBlog(true)", 10); </script> <!--狗狗已杀死--><a href="http://www2.clustrmaps.com/counter/maps.php?url=http://fx.jiuzhe.com" id="clustrMapsLink"><img src="http://www2.clustrmaps.com/counter/index2.php?url=http://fx.jiuzhe.com" style="border:1px solid;" alt="Locations of visitors to this page" title="Locations of visitors to this page" id="clustrMapsImg" onError="this.onError=null; this.src='http://clustrmaps.com/images/clustrmaps-back-soon.jpg'; document.getElementById('clustrMapsLink').href='http://clustrmaps.com'"/> </a>
文章分类
我做过的网站
南京信息工程大学教务处
南京信息工程大学本科评估
南京信息工程大学研究生部
我自己的另一个Blog
江苏省盛泽中学99高三(4)
友情链接
Bigtaro's Blog(RSS)
Mp3tag
Xia Fang's Blog(RSS)
五月的天空(RSS)
寄托的天空(RSS)
我想有个家(RSS)
梦的点滴(RSS)
浓雾下沉默的岛(RSS)
有用的链接
CSDN
存档

原创  小函数,大问题 收藏

对于strcpy,sprintf,strcat这些不安全的函数的讨论应该算是不少了,大家都知道可以用strncpy,snprintf和strncat来替换它们。但实际工作中似乎这些“安全版”的函数带来的疑惑还是不小,总结了一下,列在这里。

  1.sprintf(char * str, const char * format, ...) -> snprintf(char * str, size_t size, const char * format, ...)

   vsprintf(char * str, const char * format, va_list ap) -> vsnprintf(char * str, size_t size, const char * format, va_list ap)

  按照C/C++标准,snprintf和vsnprintf永远不会往str中输出多于size所指定的字节数的字符(包括结尾的'\0'),它们也保证了一定会在str中写入'\0',所以在使用这个函数后不用担心结尾的问题。

  举例:

  char buf[5];
  snprintf(buf, 5, "This is a test string."); // buf becomes "This", buf[4] is '\0'
  snprintf(buf, 6, "This is a test string."); // ERROR: buffer overflow
  snprintf(buf, 5, "abc"); // buf becomes "abc", the value of buf[3] is '\0', buf[4] is undefined.
然而,VC中的_snprintf函数并没有按照这样的规定来做,它在输出缓冲区不够大时就不会输出结尾的'\0'(跟strncpy的行为类似)。所以要让上面的程序工作正常,必须做相应的修改。
  char buf[5];
  _snprintf(buf, 5, "This is a test string.");// buf becomes "This ", buf[4] is ' '
  buf[4] = 0; // buf[4] is '\0' now.
  _snprintf(buf, 6, "This is a test string."); // ERROR: buffer overflow
  _snprintf(buf, 5, "abc"); // buf becomes "abc", the value of buf[3] is '\0', buf[4] is undefined.
如果要保证可移植性,就得按VC的写法,做一次对于标准来说很多余的“填0”的操作,再通过定义宏来区别平台分别选用snprintf或_snprintf。

  2. strcat(char * dest, const char * src) -> strncat(char * dest, const char * src, size_t n);

  这个函数比较简单,它保证不会写入多于n+1个字符,并且保证最后一定以'\0'结束。

  举例:

  char dest[5] = "abc";
  strncat(dest, "defghijklmn", 5 - 3 - 1); // dest becomes "abcd", dest[4] is '\0',
   // always minus the buffer length by 1 as the value of n.
  strncat(dest, "defghijklmn", 5 - 3); // ERROR: buffer overflow

  3. strcpy(char * dest, const char * src) -> strncpy(char * dest, const char * src, size_t n);

  strncpy是一个比较容易出错的函数,它保证复制src中不多于n字节的内容,但是如果src的前n个字节中没有包含'\0',就会导致 dest没有正常的以'\0'终止。另外,它还保证如果src的长度小于n,则dest剩余的部分都会以'\0'填充。在用这个函数时,有一个最佳实践就 是先把dest以0填充,并传入dest的长度减1的值作为n,这样可以确保安全。

  举例:

  char buf[5] = {0}; // Always zero-fill the buffer,
   // always use this form to initialize the stack arrays to get
   //better performance over memset.
  char * buf2 = new char[5];
  memset(buf2, 0, 5); // Always zero-fill the buffer
  strncpy(buf, "abcde", 5); // ERROR: buf is not null-terminated.
  strncpy(buf2, "abcde", 5 - 1); // Right, always minus the buffer length by 1
   //as the value of n. buf becomes "abcd", buf[4]
   //is '\0' by initilization;
  // This is a common error in the existing code.
  char buf3[5];
  const char * str = "Test";
  strncpy(buf3, str, strlen(str)); // Wrong, buf may not null-terminated,
   // potential buffer-overflow
  strncpy(buf3, str, strlen(str)+1); // Wrong, potential buffer-overflow.
   //No difference with using strcpy.
 

发表于 @ 2007年04月11日 22:18:00 | 评论( loading... ) | 编辑| 举报| 收藏

旧一篇:CSDN技术英雄会流水帐 | 新一篇:What is Free Software?

  • 发表评论
  • 评论内容:
  •  
Copyright © lifanxi
Powered by CSDN Blog