6

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

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,它是如何工作的(语法方面:显然它不需要两个参数)。

4

7 回答 7

29

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

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

无需担心缓冲区大小和所有这些东西。如果你有一个需要 a 的 API const char *,你可以只使用.c_str()成员;

some_c_api(prefix.c_str());
于 2009-06-01T20:33:03.340 回答
27

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

strcat_s 通过强制您传入要复制字符串的缓冲区的长度来解决此问题;如有必要,它将截断字符串以确保缓冲区没有溢出。

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

于 2009-06-01T20:02:38.843 回答
5

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

_CRT_SECURE_NO_WARNINGS

_SCL_SECURE_NO_WARNINGS

到您项目的预处理器定义。

于 2009-06-01T20:41:04.290 回答
4

因为它无法检查您案例中的目标字符串(前缀)是否会超出其范围。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))并将其作为计数传递。

于 2009-06-01T20:02:33.370 回答
4

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

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

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

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

于 2009-06-01T20:04:10.183 回答
4

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

#pragma warning(disable:4996)

顺便说一句,我强烈建议您使用 strcat_s()。

于 2009-06-01T22:58:16.930 回答
0

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

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

您必须沿着两个字符串的整个长度走,以确保它适合,然后再沿着它们的整个长度走一遍以进行复制。因此,许多程序员会简单地假设它适合并跳过测试。更糟糕的是,可能是在第一次编写代码时,它是保证适合的,但是当有人添加另一个 strcat,或者在程序的其他地方更改缓冲区大小或常量时,你现在遇到了问题。

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

于 2009-06-01T21:15:16.250 回答