如何将当前strcpy转换为strcpy_s?

时间:2017-05-03 09:31:39

标签: c string strcpy

我有大型项目,strcpy到处使用。我想使用strcpy_s代替strcpy。我认为差不多有10,000次使用strcpy。改变每一个strcpy是如此麻烦。有没有有效的转换方式?

3 个答案:

答案 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甚至是字符串的独特内容,而是代码中每个数组必须考虑的内容。