1. 背景


好多人已经知道利用strncpy替代strcpy来防止缓冲区越界。
但是如果还要考虑运行效率的话,也许strlcpy是一个更好的方式。

2. strcpy


strcpy 是依据 /0 作为结束判断的,如果 to 的空间不够,则会引起 buffer overflow。
strcpy 常规的实现代码如下:

char * strcpy(char *to, const char *from)
{
char *save = to; for (; (*to = *from) != '/0'; ++from, ++to);
return(save);
}

但通常,我们的 from 都来源于用户的输入,很可能是非常大的一个字符串,因此 strcpy 不够安全。

2. strncpy


在 ANSI C 中,strcpy 的安全版本是 strncpy

char *strncpy(char *s1, const char *s2, size_t n);

但 strncpy 其行为是很诡异的(不符合我们的通常习惯)。标准规定 n 并不是 sizeof(s1),而是要复制的 char 的个数。一个最常见的问题,就是 strncpy 并不帮你保证以'/0'结束。

char buf[8];
strncpy( buf, "abcdefgh", 8 );

看这个程序,buf 将会被 “abcdefgh” 填满,但却没有 '/0' 结束符了。
另外,如果 s2 的内容比较少,而 n 又比较大的话,strncpy 将会把之间的空间都用 '/0' 填充。这又出现了一个效率上的问题,如下:

char buf[80];
strncpy( buf, "abcdefgh", 79 );

上面的 strncpy 会填写 79 个 char,而不仅仅是 “abcdefgh” 本身。
strncpy 的标准用法为:(手工写上 '/0'

strncpy(path, src, sizeof(path) - 1);
path[sizeof(path) - 1] = '/0';
len = strlen(path);

3. strlcpy


// Copy src to string dst of size siz. At most siz-1 characters
// will be copied. Always NUL terminates (unless siz == 0).
// Returns strlen(src); if retval >= siz, truncation occurred.
size_t strlcpy(char *dst, const char *src, size_t siz);

使用 strlcpy,就不需要我们去手动负责'/0' 了,仅需要把 sizeof(dst) 告之 strlcpy 即可:

strlcpy(path, src, sizeof(path));
len = strlen(path);
if ( len >= sizeof(path) )
printf("src is truncated.");

并且 strlcpy 传回的是 strlen(str),因此我们也很方便的可以判断数据是否被截断。

[* 一点点历史 *]

strlcpy 并不属于 ANSI C,至今也还不是标准。
strlcpy 来源于 OpenBSD 2.4,之后很多 unix-like 系统的 libc 中都加入了 strlcpy 函数,我个人在 FreeBSD、Linux 里面都找到了 strlcpy。(Linux使用的是 glibc,glibc里面有 strlcpy,则所有的 Linux 版本也都应该有 strlcpy)
但 Windows 下是没有 strlcpy 的,对应的是strncpy和memset函数
本篇文章来源于 Linux公社网站(www.linuxidc.com)
原文链接:http://www.linuxidc.com/Linux/2012-06/61893.htm

最新文章

  1. spider_getModelInformation
  2. html 元素 绝对位置坐标
  3. java.lang.Boolean为null时
  4. 在Swift中使用libxml2
  5. 控制寄存器 CR*
  6. IOS数据本地存储的四种方式--
  7. win10 uwp InkCanvas控件数据绑定
  8. 【Java入门提高篇】Day10 Java代理——静态代理
  9. Kafka监控安装
  10. EBS HRMS数据表
  11. Spring boot项目maven的profile多环境配置不自动替换变量的问题解决
  12. nargin
  13. Python中的logging模块【转】https://www.cnblogs.com/yelin/p/6600325.html
  14. POJ2516 Minimum Cost【最小费用最大流】
  15. Docker Engine SDKs and API 的开发2
  16. SHU oj 422 风力观测 线段树
  17. C代码与C++代码之间的相互调用
  18. 1.3.7、CDH 搭建Hadoop在安装之前(端口---第三方组件使用的端口)
  19. 数据包编辑工具bittwiste
  20. STM32F4, USB HS with ULPI and Suspend/Wakeup

热门文章

  1. log4j详细配置解析
  2. Unslider--入门篇
  3. nginx配置 location root alias
  4. input标签附带提示文字(bootstrap里面输入框的两侧同时添加额外元素)
  5. noip2015提高组day2解题报告
  6. 你知道在springboot中如何使用WebSocket吗
  7. Raspberry Pi学习笔记
  8. Android新手入门2016(7)--布局
  9. shell mysql 直接创建表
  10. 创建JDBC模板简化代码、JDBC应用的事务管理以及连接池的作用