我有大型项目,strcpy
到处使用。我想使用strcpy_s
代替strcpy
。我认为差不多有10,000次使用strcpy
。改变每一个strcpy
是如此麻烦。有没有有效的转换方式?
答案 0 :(得分:4)
如果不进行检查,你真的不应该这样做,因为如果没有智能地完成缓冲管理,那么它就会丢失。
由于目标缓冲区的性质(例如静态或堆分配)对于strcpy_s()
的正确参数非常重要,并且当然在现有{{1}中不存在该信息调用,你必须以任何方式添加它。这需要一个人。
通常像strcpy()
之类的调用可以转换为strcpy(dest, src);
,但如果strcpy_s(dest, sizeof dest, src);
是堆分配的,那么这只是指针的大小而不是指向的缓冲区。当然是错的。
答案 1 :(得分:1)
鉴于您已经提供了一个无法推断出的额外参数(size_t destsz
),这个参数必须准确无误才能从您所遇到的变化中获益。
使用strcpy()
10,000次的应用程序听起来很疯狂,但您就在身边。
<强>第一强> 如果您的时间/资源有限,那么我建议的只是一点风险评估。 哪些调用正在复制外部数据(来自文件,操作系统,用户,端口或套接字等)。 专注于确保那些不会被覆盖,并且您将更有效地降低风险。
<强>第二强> 如果您有任何标准变量名称和标准最大尺寸&#39;你可以做一些全局搜索和替换。
假如您在平台上使用filename
并且文件名最多为255个字符(加上NUL),则可以将strcpy(filename,
替换为(例如)strcpy_s(filename,FILENAME_MAX_SZ
。
如果代码遍布整个地方&#39;你已经完成了很多工作。
用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上失败,因为他们不同意如何解决控制类型!见Document: N1930 (controlling expression of _Generic)
快乐狩猎。
答案 2 :(得分:0)
为什么要替换strcpy()函数? There is nothing wrong with strcpy。故意将其更改为strcpy_s
无法解决任何问题。您需要做的是考虑每个案例:
这不是strcpy
甚至是字符串的独特内容,而是代码中每个数组必须考虑的内容。