如何将当前的strcpy转换为strcpy_s?

问题描述 投票:0回答:3

我有一个大型项目,到处都使用

strcpy
。我正在考虑使用
strcpy_s
而不是
strcpy
。我想我已经使用了近一万次
strcpy
。每一个
strcpy
都换,太麻烦了。有什么有效的转换方法吗?

c string strcpy
3个回答
6
投票

你真的不应该在没有检查的情况下这样做,因为如果不明智地完成,那么加强缓冲区管理的意义就会丧失。

由于目标缓冲区的性质(例如静态或堆分配)在涉及

strcpy_s()
的正确参数时非常重要,并且该信息当然不存在于现有
strcpy()
调用中,因此您 必须以任何方式添加它。这需要人类。

通常像

strcpy(dest, src);

 这样的调用可以转换为 
strcpy_s(dest, sizeof dest, src);
,但如果 
dest
 是堆分配的,这将只是指针的大小,而不是指向的缓冲区的大小,这当然是错误的。


2
投票
为什么要替换strcpy()函数?

strcpy 没有任何问题。教条地将其更改为 strcpy_s

 不会解决任何问题。您需要做的是考虑每个个案:

    源缓冲区的大小是否已知并且其内容是否已验证?
  • 源缓冲区是否具有动态特性?它的大小可以变化吗?或者您知道编译时的最大大小吗?
  • 目标缓冲区的大小是否足够大?它到底指向分配的内存吗?
这不是

strcpy

 甚至字符串所独有的东西,而是代码中每个 
array 都必须考虑的东西。


2
投票
鉴于您必须提供一个无法推导的附加参数 (

size_t destsz

),该参数必须准确才能从更改中受益,您遇到了真正的问题。

使用 10,000 次

strcpy()

 的应用程序听起来很疯狂,但你就在这儿。

第一 如果您的时间/资源有限,那么我所能建议的就是进行一些风险评估。 哪些调用正在复制外部数据(来自文件、操作系统、用户、端口或套接字等)。 专注于确保这些内容不会被覆盖,您将更有效地降低风险。

第二个 如果您有任何标准变量名称和标准“最大大小”,您也许可以进行一些全局搜索和替换。

假设您经常使用

filename

 并且您的平台上的文件名最多为 255 个字符(加上 NUL),您可以将 
strcpy(filename,
 替换为(例如)
strcpy_s(filename,FILENAME_MAX_SZ

如果代码“到处都是”,那么你就需要做很多工作了。

strcpy(v,

 替换为 
strcpy_s(v,SIZE_MAX
(使用正则表达式)是一个肤浅的困境,除了可能潜入组织代码质量脚本之外,实际上不会为您带来任何好处。我没有告诉你这样做! ;)

第三 如果你想在C11的世界里漫步_Generic

你可以尝试这样的:

#define __STDC_WANT_LIB_EXT1__ #include <stdio.h> #include <stdlib.h> #include <string.h> int strcpy_s(char *dest,size_t destsz,const char *src){ if(strlen(src)>=destsz){ return 1; } strcpy(dest,src); return 0; } char *d_strcpy(char *dest,const char *src){ #ifndef NDEBUG fprintf(stdout,"unsafe copy of %s\n",src); #endif return strcpy(dest,src); } #define strcpy(dest,src) _Generic (dest,\ char[100] : strcpy_s(dest,sizeof dest,src),\ char*: d_strcpy(dest,src)\ ) int main(void) { char a[100]={'A','B','\0'}; char *b=malloc(10*sizeof(char)); strcpy(a,"XXX"); strcpy(b,"XYX"); printf("%s %s\n",a,b); free(b); return 0; }
不幸的是,您确实需要指定数组大小,因此需要使用可能有限的“最大大小”列表,虽然这应该适用于 Clang(未经测试),但它在 GCC 上失败,因为它们不同意如何解析控制类型!请参阅

文档:N1930(控制_Generic的表达)

狩猎快乐。

© www.soinside.com 2019 - 2024. All rights reserved.