c - strncpy_s() - 安全字符串复制 - 处理所有可能的极端情况的正确用法应该是什么?

标签 c string strcpy strncpy

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

strncpy_s() 在此链接中有更多描述 - https://en.cppreference.com/w/c/string/byte/strncpy

我正在考虑在我的代码库中使用这个函数 - strncpy_s() 来处理所有可能的情况,其中它的老兄弟通常无法处理 - 例如当 srcString 比 destString 长时。或者如果 srcString 不是 NULL 终止。

所以我想知道 strncpy_s() 的用法应该是 -

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

优雅地处理所有可能的情况 - 即

  1. 当 srcString 大于 destString 时,则截断 srcString 到长度 destString。
  2. 当destString大于srcString时,则复制整个内容 srcString 到 destString,以 NULL 结尾。
  3. 当 srcString 和 destString 长度相同时,则复制整个字符串 srcString 的内容到 destString,以 NULL 结尾。
  4. 当 srcString 不以 NULL 结尾时。如果 srcString 小于 destString 然后将 srcString 的内容复制到 destString 以 NULL 终止。如果 destString 小于 srcString 然后从 srcString 复制 destString 大小的内容。

有人会认为上述 strncpy_s() [1] 的用法在任何情况下都可能失败,而我无法想到吗?

编辑:我已经更新了场景中采取的操作 - (2)、(3) 和 (4)

最佳答案

您根本不应该使用strncpy_s;它是附件 K 函数之一,从未作为任何 C 库的集成部分实现(微软的编译器实现了一组具有相似名称和不同语义的重叠函数),目前正在考虑从标准中删除。 (有关此内容的更多信息,请参阅 this old answer 及其链接到的各种文档。)

您应该编写自己的函数,使用 strlenmemmove 和离散逻辑的组合来准确实现您想要的行为。您说当目标缓冲区太小时您希望截断字符串。您没有说出当目标缓冲区至少足够大时您希望发生什么,但明显要做的事情是复制整个字符串并停止。而且你也没有说出当 srcString 不是 NUL 终止时你想要发生什么,但在这种情况下正确的做法是崩溃(参见 this old post from The Old New Thing about why -抱歉,没有段落分隔符,请在中间的某个位置查找“你应该崩溃”)。因此:

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 的大小(如果是堆分配)。

关于c - strncpy_s() - 安全字符串复制 - 处理所有可能的极端情况的正确用法应该是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63327838/

相关文章:

c - 如何在PowerPC架构中 "invalidate"或 "flush"范围内的CPU缓存?

c++ - 在自己的 C++ 项目中使用 Simulink 生成的 C/C++ 代码

c++ - C语言中extern存储类说明符的重要性和用法

android - 将 String[] 从一个 Activity 传递到另一个 Activity

C-strcpy 指针

c - 当我尝试使用 glsl 用 opengl 和 glew 绘制三角形时出现问题

java - 显示弹出窗口一次?

ruby-on-rails - 将嵌套数组的字符串表示形式转换为数组

c - 调用 strcpy 时出现段错误

c++ - strcpy 及其第二个参数出错