strcpy... 想用 strcpy_mine 替换,它将 strncpy 和 null 终止

Posted

技术标签:

【中文标题】strcpy... 想用 strcpy_mine 替换,它将 strncpy 和 null 终止【英文标题】:strcpy... want to replace with strcpy_mine which will strncpy and null terminate 【发布时间】: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 不可用)

【问题讨论】:

【参考方案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'; :-)

以上是关于strcpy... 想用 strcpy_mine 替换,它将 strncpy 和 null 终止的主要内容,如果未能解决你的问题,请参考以下文章

strcpy&memcpy理解

如何将当前的 strcpy 转换为 strcpy_s?

strcpy和memcpy的区别

c 语言 strcpy

strcpy和memcpy的区别

strcpy()函数和strcmp()函数怎么用?