我有一个大型项目,到处都使用
strcpy
。我正在考虑使用 strcpy_s
而不是 strcpy
。我想我已经使用了近一万次strcpy
。每一个strcpy
都换,太麻烦了。有什么有效的转换方法吗?
你真的不应该在没有检查的情况下这样做,因为如果不明智地完成,那么加强缓冲区管理的意义就会丧失。
由于目标缓冲区的性质(例如静态或堆分配)在涉及
strcpy_s()
的正确参数时非常重要,并且该信息当然不存在于现有 strcpy()
调用中,因此您 必须以任何方式添加它。这需要人类。
通常像 strcpy(dest, src);
这样的调用可以转换为
strcpy_s(dest, sizeof dest, src);
,但如果
dest
是堆分配的,这将只是指针的大小,而不是指向的缓冲区的大小,这当然是错误的。
strcpy 没有任何问题。教条地将其更改为 strcpy_s
不会解决任何问题。您需要做的是考虑每个个案:
strcpy
甚至字符串所独有的东西,而是代码中每个array 都必须考虑的东西。
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 上失败,因为它们不同意如何解析控制类型!请参阅狩猎快乐。