strncpy_s()-secure string copy-的正确用法应该是什么来处理所有可能的紧急情况?

strncpy_s()-secure string copy-的正确用法应该是什么来处理所有可能的紧急情况?,c,string,strcpy,strncpy,C,String,Strcpy,Strncpy,我了解了函数-strncpy_s(),它被称为字符串复制的安全版本。比函数-strcpy()和strncpy()更安全 strncpy_s()将在本链接中详细介绍- 我正在考虑在代码库中使用这个函数-strncpys()来处理所有可能的情况,其中它的较年长的同级通常无法处理,比如srcString比destString长。或者如果srcString不是以NULL结尾的 所以我想知道strncpys()的用法应该是什么- strncpy_s(destString,sizeof(destStrin

我了解了函数-strncpy_s(),它被称为字符串复制的安全版本。比函数-strcpy()和strncpy()更安全

strncpy_s()将在本链接中详细介绍-

我正在考虑在代码库中使用这个函数-strncpys()来处理所有可能的情况,其中它的较年长的同级通常无法处理,比如srcString比destString长。或者如果srcString不是以NULL结尾的

所以我想知道strncpys()的用法应该是什么-

strncpy_s(destString,sizeof(destString),srcString,(sizeof(srcString)>sizeof(destString)?(sizeof(destString)-1:(sizeof(srcString)-1))-[1]

优雅地处理所有可能的场景-即

  • 当srcString大于destString时,则截断 srcString到destString的长度
  • 当destString大于srcString时,复制整个内容 srcString到destString的值,终止为空
  • 当srcString和destString长度相同时,复制整个 将srcString的内容转换为以NULL结尾的destString
  • 当srcString不是以NULL结尾时。如果srcString小于 destString然后将srcString内容中的一个复制到 终止为空的字符串。如果destString小于srcString 然后从srcString复制大小为destString的内容
  • 有人会认为上面提到的strncpy_()[1]的用法在任何情况下都会失败,这是我无法想象的吗


    编辑:我已更新了在场景-(2)、(3)和(4)中采取的操作您根本不应该使用
    strncpy\s
    ;它是附录K函数之一,从未作为任何C库的集成部分实现过(Microsoft的编译器实现了一组具有相似名称和不同语义的重叠函数),目前正在考虑从标准中删除。(有关这方面的更多信息,请参阅及其链接到的各种文档。)

    相反,您应该编写自己的函数,使用
    strlen
    memmove
    和离散逻辑的组合来实现您想要的行为。您说希望在目标缓冲区太小时截断字符串。当目标缓冲区至少足够大时,您不会说希望发生什么,但显然要做的是复制整个字符串并停止。当
    srcString
    未以NUL结尾时,您也不会说您希望发生什么,但在这种情况下,正确的做法是崩溃(请参阅-对于没有分节符表示抱歉,请在中间的某个位置查找“您应该崩溃”)。因此:

    void safe_strncpy(char *dest, size_t destsz, char *src)
    {
        size_t srcsz = strlen(src);  // crash here if not nul-terminated
        if (srcsz > destsz - 1)
            srcsz = destsz - 1;
        memmove(dest, src, srcsz);   // memmove is safe if dest and src overlap
        dest[srcsz] = '\0';
    }
    
    调用就像调用strcpy一样,但也提供目标缓冲区的大小。请记住,目标缓冲区的大小是而不是它可能恰好包含在程序中的任何字符串的大小。目标缓冲区的大小是您用它声明的大小(如果是变量)或传递给
    malloc
    (如果是堆分配)。

    我非常同意不使用
    strncpy\s()


    我想提供替代代码,以满足OP的目标

  • 当srcString大于destString时,将srcString截断为destString的长度
  • 我还希望不要检查
    srcString
    元素之外的
    destsz
    数据。这样做的副作用是在
    srcString
    beyond
    destsz
    中不需要空字符

  • 当destString大于srcString时
  • 当srcString和destString长度相同时
  • 当srcString不是NULL时,以NULL字符结尾
  • 特别是,在返回值中返回故障的明确指示。
    在所有情况下,
    dest!=NULL
    dest>0
    dest
    将指向具有NULL字符的字符串

    下面的代码不仅解决了OP的问题,还使用
    memmove()
    处理缓冲区重叠的情况


    我想知道strncpy_s()sizeof(destString
    的用法是否应该使用编译时
    sizeof
    ,您不妨编写一个
    static\u assert
    @kamilCuk您能详细说明一下您的想法吗?我无法理解它比函数-strcpy()和strncpy()更安全不完全是。它们实际上是不可移植的版本,可以将您的代码锁定到Microsoft,但不会更安全“微软为了提高API的采用率而对标准函数的反对,导致了一个普遍存在的谬论,即对标准函数的每次调用都必然是不安全的,应该用对“更安全”API的调用来代替。”(续)Microsoft Visual Studio实现了早期版本的API。但是,该实现不完整,既不符合C11,也不符合原始TR 24731-1……由于与规范存在大量偏差,Microsoft实现不能被视为符合或可移植。“或者换言之:一种迫使用户在可以想象的最基本任务中使用这种语言的语言对于严肃的软件开发来说是不可用的。@Peter,Monica,我不理解你的观点。你的观点是人们不应该回答这个问题吗?你的观点是提出的解决方案是错误的吗?你的观点是正确的吗?”“不适用于严肃的软件开发“?有趣的是,很多关键系统都能成功运行。就像……世界上有称职的程序员……和……最佳实践……和……代码审查和……单元测试、集成测试、系统测试和验收测试都是一件事。@bolov不,人们当然应该发布代码。但是,成功
    // Return error flag
    bool sf_strncpy(char *dest, size_t destsz, const char *src) {
      // Optional pointer test
      if (dest == NULL) return true;
    
      // Size test
      if (destsz == 0) return true;
    
      // Optional pointer test
      if (src == NULL) ( dest[0] = '\0'; return true; }
    
      // Look for null character, but not beyond destsz
      const char *end = memchr(src, '\0', destsz);
      if (end == NULL) {
        memmove(dest, src, destsz - 1);
        dest[destsz - 1] = '\0';
        return true;
      }
      memmove(dest, src, end - src);
      return false;
    }