'strncpy'对''sprintf'

Vij*_*jay 15 c printf strncpy

我可以sprintf在我的应用程序中看到许多用于复制字符串的内容.

我有一个字符数组:

char myarray[10];
const char *str = "mystring";
Run Code Online (Sandbox Code Playgroud)

现在,如果我想要将字符串复制strmyarray,最好使用:

sprintf(myarray, "%s", str);
Run Code Online (Sandbox Code Playgroud)

要么

strncpy(myarray, str, 8);
Run Code Online (Sandbox Code Playgroud)

R..*_*R.. 39

根本不应该使用它们.

  1. sprintf是危险的,被弃用的,被取代的snprintf.使用旧的sprintf安全字符串输入的唯一方法是在调用之前测量它们的长度sprintf,这是丑陋且容易出错的,或者通过添加字段精度说明符(例如,%.8s或者%.*s对于大小限制使用额外的整数参数).这也是丑陋且容易出错的,特别是如果%s涉及多个说明符.

  2. strncpy也很危险 它不是缓冲区大小限制版本strcpy.它是将字符复制到固定长度,空填充(与空终止相对)数组的函数,其中源可以是C字符串或至少是目标大小的固定长度字符数组.它的用途是用于传统的unix目录表,数据库条目等,它们使用固定大小的文本字段,并且不想在磁盘或内存中浪费单个字节以进行空终止.它可能被误用为缓冲区大小限制strcpy,但这样做有害有两个原因.首先,如果整个缓冲区用于字符串数据(即源字符串长度至少与dest缓冲区一样长),则无法终止null.您可以自己添加终止,但这很难看并且容易出错.第二,strncpy当源字符串短于输出缓冲区时,始终使用空字节填充完整目标缓冲区.这只是浪费时间.

那么你应该用什么呢?

有些人喜欢BSD strlcpy功能.从语义上讲,它与snprintf(dest, destsize, "%s", source)返回值相同,size_t并且不会INT_MAX对字符串长度施加人为限制.但是,最流行的非BSD系统缺乏strlcpy,并且很容易编写自己的危险错误,因此如果您想使用它,您应该从可信赖的来源获得安全,已知的工作版本.

我的偏好是简单地snprintf用于任何非平凡的字符串构造,而strlen+ memcpy用于一些被测量为性能关键的琐碎案例.如果你养成了正确使用这个习惯用法的习惯,几乎不可能意外地编写带有字符串相关漏洞的代码.

  • 我认为`strncpy`的"预期用途"主要是一个已经失去其实用性的概念...... (3认同)