【问题标题】:strlcpy in terms of strncpy on platforms that don't have strlcpystrlcpy 在没有 strlcpy 的平台上的 strncpy
【发布时间】:2017-08-15 17:12:00
【问题描述】:

我知道,strlcpystrncpy 更安全,同时从源字符数组复制到我们希望目标为空终止的目标字符数组, 下面的包装器可以吗?

size_t strlcpy(char *dst, const char *src, size_t size) {
  if (size != 0) {
    int maxSize = size - 1;
    int currSize = -1;
    while ((++currSize < maxSize) && (*dst++ = *src++));
    *dst = 0;
    return currSize;
  }
  return 0;
}

请发表评论。

【问题讨论】:

    标签: c arrays string copy strncpy


    【解决方案1】:

    您的实现非常快,但有两个怪癖:

    • 一个怪癖是当有足够的空间时,您的函数会写入两个 NUL 字符而不是一个。
    • 另一个怪癖是返回值并不表示问题。

    除了这些怪癖之外,您的版本在功能上等同于 strxcpy() by attractivechaos。但是,根据我使用的机器,您的代码会快 30-100%。在这方面做得很好!

    关于返回值,以下是我观察到的差异:

    • originalstrlcpy 返回 src 的长度:

      • 缺点: 不安全不必要的慢
      • 优点: strlcpy(d,s,n) 等同于 snprintf(d,n,"%s",s)
    • strxcpy 由有吸引力的混沌返回写入的字节数:

      • 优点: 当 src 太长时,返回值并不能清楚地表明问题
      • 缺点:返回值与 strlcpy 有偏差
    • 您的函数返回写入的字符串长度的长度:

      • 缺点:
        • 当 src 太长时,返回值不能明确指出问题
        • 返回值不表示是否写入了 NUL 字符
      • 优点:更符合原strlcpy。

    在我的首选实现中,所有提到的功能缺点都已修复:

    ssize_t safe_strlcpy(char *dst, const char *src, size_t size)
    {
        if (size == 0)
            return -1;
    
        size_t ret = strnlen(src, size);
        size_t len = (ret >= size) ? size - 1 : ret;
        memcpy(dst, src, len);
        dst[len] = '\0';
        return ret;
    }
    

    src 太长且不完全适合时,它返回size; -1 如果size 为零;否则 - 写入字符串长度。所以,当一切正常的时候,返回值还是和strlcpy一致的。并且它基于原始strlcpy的Git's implementation

    【讨论】:

      【解决方案2】:

      检查size 是否大于零会产生误导,因为size_t 是无符号的。更易读的检查是if (size != 0) ...

      另一个问题是strncpy 用零填充其目的地直到s,而strlcpy 没有这样做。如果您想匹配strlcpy 的行为,请在不可用的系统上编写自己的实现,而不是依赖strncpy

      【讨论】:

        猜你喜欢
        • 2011-10-22
        • 1970-01-01
        • 2022-11-05
        • 2020-09-11
        • 2021-12-19
        • 1970-01-01
        • 1970-01-01
        • 2020-12-08
        • 1970-01-01
        相关资源
        最近更新 更多