为什么MSVC ++认为“std :: strcat”是“不安全的”? (C ++)

时间:2009-06-01 19:57:27

标签: c++ warnings strcat strcat-s

当我尝试做这样的事情时:

char* prefix = "Sector_Data\\sector";
char* s_num = "0";
std::strcat(prefix, s_num);
std::strcat(prefix, "\\");

依此类推,我收到警告

warning C4996: 'strcat': This function or variable may be unsafe. Consider using strcat_s instead.

为什么strcat被认为是不安全的,有没有办法在不使用strcat_s的情况下摆脱这个警告?

另外,如果摆脱警告的唯一方法是使用strcat_s,它是如何工作的(语法方面:显然它不需要两个参数)。

7 个答案:

答案 0 :(得分:29)

如果您使用的是c ++,为什么不避免整个混乱并使用std::string。没有任何错误的相同示例将如下所示:

std::string prefix = "Sector_Data\\sector";
prefix += "0";
prefix += "\\"

无需担心缓冲区大小和所有这些问题。如果您的API有const char *,则可以使用.c_str()成员;

some_c_api(prefix.c_str());

答案 1 :(得分:27)

因为缓冲区前缀的空间可能比复制到它的空间少,导致缓冲区溢出。 因此,黑客可以传入一个特制的字符串,该字符串会覆盖返回地址或其他关键内存,并开始在程序的上下文中执行代码。

strcat_s通过强制你传入要复制字符串的缓冲区的长度来解决这个问题;如果需要,它会截断字符串,以确保缓冲区不会溢出。

google strcat_s以准确了解如何使用它。

答案 2 :(得分:4)

这是C / C ++中的一个字符串操作函数,可能导致缓冲区溢出错误。

问题是该函数不知道缓冲区的大小。从MSDN文档:

  

第一个参数strDestination,   必须大到足以容纳   当前的strDestination和strSource   合并并关闭'\ 0';   否则,可能会发生缓冲区溢出。

strcat_s需要一个额外的参数来告诉它缓冲区的大小。这允许它在执行concat之前验证大小,并防止超出。见http://msdn.microsoft.com/en-us/library/d45bbxx4.aspx

答案 3 :(得分:4)

您可以添加以下内容来消除这些警告:

_CRT_SECURE_NO_WARNINGS

_SCL_SECURE_NO_WARNINGS

到项目的预处理器定义。

答案 4 :(得分:4)

要关闭警告,您可以执行此操作。

#pragma warning(disable:4996)
不过,我强烈建议您使用strcat_s()。

答案 5 :(得分:3)

因为它无法检查您的案例中的目标字符串(前缀)是否将被写入其边界之外。 strcat本质上是通过循环工作,将源字符串逐字节复制到目标。当它看到一个名为“0”的值(由'\ 0'表示)时,它会停止,称为空终端。由于C没有内置边界检查,并且dest str只是内存中的一个位置,strcat将继续进入ad-infinidium,即使它超过源str或dest。 str没有空终端。

上述解决方案是针对您的Windows环境的特定于平台的。如果你想要平台独立,你必须与strncat争论:

strncat(char* dest, const char* src, size_t count)

智能使用时,这是另一种选择。您可以使用count指定要复制的最大字符数。要做到这一点,你必须弄清楚dest中有多少可用空间(你分配了多少 - strlen(dest))并将其作为计数传递。

答案 6 :(得分:0)

strcat有两个问题。首先,您必须在函数外部进行所有验证,完成与函数几乎相同的工作:

if(pDest+strlen(pDest)+strlen(pScr) < destSize)

你必须沿着两个琴弦的整个长度向下走,以确保它适合,然后沿着它们的整个长度走下去做副本。因此,许多程序员只会假设它适合并跳过测试。更糟糕的是,可能是当代码首次编写时,它是值得保证的,但是当有人添加另一个strcat,或者在程序中的其他地方更改缓冲区大小或常量时,您现在就会遇到问题。

另一个问题是pSrc和pDst是否重叠。根据你的编译器,strcat很可能是简单的循环,它一次在pSrc中检查一个字符为0。如果pDst覆盖了0,那么你将进入一个循环,直到程序崩溃为止。