【问题标题】:strcpy... want to replace with strcpy_mine which will strncpy and null terminatestrcpy... 想用 strcpy_mine 替换,它将 strncpy 和 null 终止
【发布时间】:2010-10-31 08:51:55
【问题描述】:

线索在标题中,但基本上我继承了一些包含 800 多个 strcpy 实例的代码。我想写一个新函数,然后用 strcpy_mine 替换 strcpy。

所以我正在尝试计算 strcpy_mine 的参数列表。

我试过了:

void strcpy_mine( char* pTarget, const char* const pCopyMe )
{
  const unsigned int lenAlwaysFour = sizeof(pCopyMe ); //:(
  strncpy( pTarget, pCopyMe, lenAlwaysFour );

  //add extra terminator in case of overrun
  pTarget[lenAlwaysFour] = 0;
}

但是sizeof总是4 pCopyMe是一个指针

我不想做的是替换

strcpy (buf, pCopyMe);

strncpy (buf, pCopyMe, sizeof(pCopyMe)); buf[sizeof(pCopyMe)] = 0;

有什么想法吗? (strcpy_l 不可用)

【问题讨论】:

    标签: c++ c strcpy


    【解决方案1】:

    sizeof() 返回类型的大小 - 在这种情况下 const char* const 在 32 位机器上为 4。

    我想你认为你想要strlen()。但这不是使用 strncpy 函数的正确方法。 您需要 strncpy 的 输出 缓冲区的大小。

    要解决此问题,您需要检查每个调用站点的代码,计算输出缓冲区的大小,并将其作为参数传递给strcpy_mine。如果 strcpy(或 strcpy_mine)的调用站点不知道输出缓冲区的大小,则需要在代码中向后搜索分配缓冲区的位置,并将大小一直向下传递到 strcpy 站点.

    基本上,您不能编写一个替代 strcpy 的替代品,它采用相同的参数并希望避免首先产生 strncpy 的问题(以及除此之外的更好的替代品)。您可以创建一个函数,它采用与 strncpy 相同的参数,但确保结果以空值结尾 - 查看 OpenBSD's strlcpy() 函数的实现。但第一步必须是更改调用站点以传递有关输出缓冲区大小的信息。

    【讨论】:

    • +1 表示 strlcpy。在编写与此类似的我自己的函数时,我还将枚举 {AllOrNothing, TruncateOkay} 传递给函数以使其处理溢出情况。
    【解决方案2】:

    根据调用站点的外观,大多数情况通常可以通过简单的模板处理:

    #include <string.h>
    
    template <int bufferSize>
    void strcpy_mine( char (&pTarget)[bufferSize], const char* const pCopyMe )
    {
      strncpy( pTarget, pCopyMe, bufferSize-1 );
    
      //add extra terminator in case of overrun
      pTarget[bufferSize-1] = 0;
    }
    
    int main()
    {
      char buf[128];
      strcpy_mine(buf,"Testing");
      return 0;
    }
    

    如果您使用的是 Microsoft Visual Studio 2005 或更高版本,请参阅 Secure Template Overloads 了解 Microsoft 实施。

    【讨论】:

    • 干杯!这几乎是我所追求的,但它仍然迫使我通过 char buf[200] 将缓冲区的大小放在人字形中。 strcpy_mine(buf, pString);
    • strCpyMine(buf, pString);
    • 我认为是过时的编译器,我使用的是 VC6;见support.microsoft.com/kb/165803
    • 我做错了什么。模板需要稍有不同。立即修复。
    【解决方案3】:

    您可以为您的 strcpy_mine 使用与 strncpy 相同的参数列表,但将其编写为始终为 null 以终止结果。应该不会很难做到。

    然而,一个挑战是,调用 strcpy() 的某些现有代码可能也不知道缓冲区的大小。

    【讨论】:

    • 我支持这个。您需要为输出缓冲区的大小添加另一个参数。 strcpy 方法是缓冲区溢出错误的典型来源。微软甚至弃用了这个函数,取而代之的是 strncpy。
    【解决方案4】:

    也许有点外围,但因为没有人提到它并且在标题中标榜:你不能(合法地)编写一个名为 strcpy_mine() 的全局函数。

    名称以str 开头的函数的“命名空间”是为标准库保留的。例如,请参阅the accepted answer to this question

    【讨论】:

      【解决方案5】:

      道格拉斯·利德说得对。替换 strcpy 的用处是有限度的,除非您愿意在每个实例中都传递一个良好、合理的缓冲区长度。工作量很大!

      好消息是,这是值得的!几年前,我参与了几个 C++ 项目,这些项目都是迟到的、有缺陷的和不可靠的。通过声明 strcpy 和 strlen 被禁止,并从项目中抽出 2-3 天用自定义 strncpy/strnlen 替换它们,在所有这些项目中,我们突然可以运行几天而不是几个小时。我们还看到屏幕显示和日志文件中出现了很多截断的字符串。这为我们提供了追踪截断问题(以前是崩溃问题)所需的线索。

      如果您不想这样做,您可以通过简单地检查两个指针​​参数是否为 NULL、限制字符串副本的最大大小和 记录所有达到边界的时间来获得小得多的好处。 不要使用任何一个参数的 strlen,因为如果字符串没有正确地以 null 终止,strlen 会很高兴地崩溃。

      现在,新项目使用良好的字符串对象,但有很多旧代码不使用。

      【讨论】:

        【解决方案6】:

        您还可以使用宏来避免多次编辑。或者通过一些脚本自动编辑。

        【讨论】:

        • 如果你关心,宏是单数,宏是复数。 Macroses不是一个词。我猜英语不是你的母语。我只是想帮你。
        【解决方案7】:

        正如其他人在上面所说的那样,您肯定需要将目标缓冲区的大小作为参数传递。

        这有点离题,但我只想指出,在您使用strncpy() 之后,您需要将缓冲区的最后一个字符设置为空,该字符的索引少1 em> 比长度(不是缓冲区的长度):

        strncpy (buf, pCopyMe, buflen); buf[buflen - 1] = '\0';
        

        或者,您可以在一个空字符串上使用strncat(),将其长度减少1,它会保证您的字符串以空值结尾:

        buf[0] = '\0'; strncat (buf, pCopyMe, buflen - 1);
        

        【讨论】:

        • 如果你仍然在它为什么不: strncpy(buf, pCopyMe, buflen)[buflen-1]='\0'; :-)
        猜你喜欢
        • 2013-11-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-28
        • 2010-11-30
        • 2019-06-01
        • 2020-07-01
        相关资源
        最近更新 更多