strcpy ,strncpy ,strlcpy的用法

好多人已经知道利用strncpy替代strcpy来防止缓冲区越界。

但是如果还要考虑运行效率的话,也许strlcpy是一个更好的方式。

1. strcpy

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

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函数

C语言中函数strcpy ,strncpy ,strlcpy的用法的更多相关文章

  1. C语言中函数strcpy ,strncpy ,strlcpy的用法【转】

    转自:http://blog.chinaunix.net/uid-20797562-id-99311.html strcpy ,strncpy ,strlcpy的用法好多人已经知道利用strncpy替 ...

  2. C语言中函数返回字符串的4中方法

    C语言中函数返回字符串的4中方法 函数的构成部分:返回类型.函数名称.参数.函数主体 参数:函数调用时传入的参数称为实参,函数定义时出现的参数为形参 形参的作用在于接收实参传入的值,形参和函数内部的其 ...

  3. c语言中函数的简单介绍

    c语言中函数的介绍: 函数,简单的说就是代码的打包.存放在一个地方,当需要的时候调用. 函数分类: 1.无参无返回值函数 void func() 2.无参有返回值函数  int func() 3.有参 ...

  4. c语言中函数参数入栈的顺序是什么?为什么

    看到面试题C语言中函数参数的入栈顺序如何? 自己不知道,边上网找资料.下面是详细解释 #include <stdio.h> void foo(int x, int y, int z){   ...

  5. C语言中函数和指针的參数传递

    近期写二叉树的数据结构实验.想用一个没有返回值的函数来创建一个树,发现这个树就是建立不起来,那么我就用这个样例讨论一下c语言中指针作为形參的函数中传递中隐藏的东西. 大家知道C++中有引用的概念,两个 ...

  6. C语言中函数参数传递

    C语言中函数参数传递的三种方式 (1)值传递,就是把你的变量的值传递给函数的形式参数,实际就是用变量的值来新生成一个形式参数,因而在函数里对形参的改变不会影响到函数外的变量的值.(2)地址传递,就是把 ...

  7. C语言中函数的调用方式

    第一眼看到这样一个题目的我,心想除了如下的直接调用还能怎么调用呢? 1 void fun(void) 2 { 3 ...... 4 //你的代码 5 ..... 6 } 7 int main(void ...

  8. Go语言中异常处理painc()和recover()的用法

    Go语言中异常处理painc()和recover()的用法 1.Painc用法是:用于抛出错误.Recover()用法是:将Recover()写在defer中,并且在可能发生panic的地方之前,先调 ...

  9. C语言——常用标准输入输出函数 scanf(), printf(), gets(), puts(), getchar(), putchar(); 字符串拷贝函数 strcpy(), strncpy(), strchr(), strstr()函数用法特点

    1 首先介绍几个常用到的转义符 (1)     换行符“\n”, ASCII值为10: (2)     回车符“\r”, ASCII值为13: (3)     水平制表符“\t”, ASCII值为 9 ...

随机推荐

  1. db2数据库的备份与还原

    前言: 数据备份的重要性: 提高系统的高可用性和灾难可恢复性:(在数据库系统崩溃的时候,没有数据库备份怎么办!) 使用数据库备份还原数据库是数据库系统崩溃时提供数据恢复最小代价的最优方案:(总不能让客 ...

  2. Packet for query is too large (4,544,730 > 4,194,304). You can change this value on the server by setting the 'max_allowed_packet' variable.

    修改 my.ini 加上 max_allowed_packet =6710886467108864=64M默认大小4194304  也就是4M修改完成之后要重启mysql服务,如果通过命令行修改就不用 ...

  3. python爬取豆瓣电影信息数据

    题外话+ 大家好啊,最近自己在做一个属于自己的博客网站(准备辞职回家养老了,明年再战)在家里 琐事也很多, 加上自己 一回到家就懒了(主要是家里冷啊! 广东十几度,老家几度,躲在被窝瑟瑟发抖,) 由于 ...

  4. 多容器共享volume

    目标: pod中 包含两个容器: tomcat和busybox, 设置volume:app-logs, 用于tomcat向其中写日志, busybox读日志文件 apiVersion: apps/v1 ...

  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">详解

    X-UA-Compatible是针对IE8新加的一个设置,对于IE8之外的浏览器是不识别的. 这个区别与content="IE=7"在无论页面是否包含<!DOCTYPE> ...

  6. Js操作DOM元素及获取浏览器高宽

    在JavaScript中,经常会来获取Document文档元素,是 HTML 文档对象模型的英文缩写,Document Object Model for HTML,是基于浏览器编程,HTML DOM ...

  7. SQLite3学习笔记(3)

    SQLite 表达式 表达式是一个或多个值.运算符和计算值的 SQL函数的组合. SQL表达式与公式类似,都写在查询语言中.您还可以使用特定的数据集来查询数据库. SELECT语句的基本语法如下: S ...

  8. LoadRunner(2)

    一.性能测试的基本概念 1.并发和在线的区别:并发的压力是一种瞬时压力,一般针对同一类型业务:在线的压力是一段时间的压力,没有并发那么集中. 规律:一般20用户并发产生的压力相当于200用户在线的压力 ...

  9. windows10下成功安装docker splash及遇到问题的解决方案

    转载出处:http://www.cnblogs.com/321lxl/p/9536616.html

  10. mybatis分页未明确的列定义

    问题出现原因是 集成mybaits时 会自动加上 select tmp_page.*, rownum row_id from ( abc )tmp_page 我的问题是 abc区域的列名有重名的,保持 ...