线索在标题中,但基本上我已经继承了一些具有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不可用)
欢呼声
答案 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)
好消息是,值得!几年前,我参加了几个C ++项目,这些项目很晚,很多,而且不可靠。通过声明禁止strcpy和strlen,并从项目中取出2-3天用自定义strncpy / strnlen替换它们,在所有这些项目中,我们突然可以运行数天而不是数小时。我们还看到屏幕显示和日志文件中出现了很多截断的字符串。这给了我们追踪截断问题所需的线索,以前崩溃的问题。
如果您不想这样做,只需检查两个指针参数为NULL,并限制字符串副本的最大大小以及记录到达边界的所有时间,您都可以获得更小的好处。 不要对任一参数执行strlen,因为如果字符串没有正确地终止,strlen会很快崩溃。
如今,新项目使用了良好的字符串对象,但是有很多遗留代码没有。