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

时间:2009-06-04 14:57:26

标签: c++ c strcpy

线索在标题中,但基本上我已经继承了一些具有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不可用)

欢呼声

7 个答案:

答案 0 :(得分:11)

sizeof()返回类型的大小 - 在本例中为const char* const,在32位计算机上为4。

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

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

基本上你不能写一个替换strcpy取代相同的参数,并希望避免首先产生strncpy的问题(​​以及更好的替换)。您可以创建一个与strncpy具有相同参数的函数,但确保结果以null结尾 - 请查看OpenBSD's strlcpy()函数的实现。但第一步必须是更改调用站点以传递输出缓冲区大小的知识。

答案 1 :(得分:4)

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

#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实施。

答案 2 :(得分:2)

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

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

答案 3 :(得分:1)

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

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

答案 4 :(得分:0)

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

答案 5 :(得分:0)

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

这有点偏离主题,但我只想指出,在使用strncpy()之后,需要将缓冲区的最后一个字符设置为null,其索引 1更少而不是长度(不是缓冲区的长度):

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

或者,您可以在空字符串上使用strncat(),将其传递的长度减去1,并且它将保证对字符串进行空终止:

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

答案 6 :(得分:0)

Douglas Leeder说的没错。替换strcpy是有用的,除非你愿意在每个实例中做一个良好,合理的缓冲区长度的繁琐工作。这是很多工作!

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

如果您不想这样做,只需检查两个指针​​参数为NULL,并限制字符串副本的最大大小以及记录到达边界的所有时间,您都可以获得更小的好处。 不要对任一参数执行strlen,因为如果字符串没有正确地终止,strlen会很快崩溃。

如今,新项目使用了良好的字符串对象,但是有很多遗留代码没有。