跳转至内容

C 编程/string.h/strcat

来自维基教科书,自由的教科书

在计算中,C 编程语言提供了一个名为 strcat 的库函数,允许将一个内存块附加到另一个内存块。这两个内存块都需要以 null 结尾。由于在 C 中,字符串不是一等公民数据类型,而是作为内存中 ASCII 字节块实现的,strcat将有效地将一个字符串附加到另一个字符串,给定两个指向已分配内存块的指针。该名称strcat是“字符串连接”的缩写。strcat位于string.h头文件中。

例如

char str1[14] = "Hello,";    /* The array has enough space for 'Hello,' plus " world!" plus a null terminator */
strcat(str1, " world!");
puts(str1);                 /* prints "Hello, world!" to stdout followed by a newline */

这是strcat:

char *
strcat(char *dest, const char *src)
{
    size_t i,j;
    for (i = 0; dest[i] != '\0'; i++)
        ;
    for (j = 0; src[j] != '\0'; j++)
        dest[i+j] = src[j];
    dest[i+j] = '\0';
    return dest;
}

的可能实现,它也可以根据其他字符串库函数定义

char *
strcat(char *dest, const char *src)
{
    strcpy(dest + strlen(dest), src);
    return dest;
}

边界错误

[编辑 | 编辑源代码]

strcat可能很危险,因为如果要附加的字符串太长,无法放入目标缓冲区,它将覆盖相邻的内存,从而引发未定义的行为。通常,程序在发生这种情况时只会导致段错误,但熟练的攻击者可以使用这种缓冲区溢出来入侵系统(参见计算机安全)。

边界检查变体

[编辑 | 编辑源代码]

为了防止缓冲区溢出,strcat已经使用了几个替代方案。它们都带有一个额外的参数,该参数对目标缓冲区的长度进行编码,并且不会写入该缓冲区结束。如果提供了不正确的长度,它们仍然会导致缓冲区溢出。

char* strncat(char* dst, const char* src, size_t n);

最常见的边界变体,strncat只附加指定数量的字节,加上一个 NULL 字节。这使得每个连接的字符串都可以使用不超过它在缓冲区的“份额”,也许是为了创建表格。它不适合更常见的需要,即获取适合缓冲区的连接字符串的前缀。为此,要传递的计数的正确值是bufferSize-strlen(buffer)-1。常见的错误是传递bufferSize, bufferSize-1bufferSize-strlen(buffer),这些都可能导致缓冲区溢出。

size_t strlcat(char* dst, const char* src, size_t size);

strlcat函数由 OpenBSD 开发者 Todd C. Miller 和 Theo de Raadt 创建,通常被认为是strncat更安全、更有用的版本。它将缓冲区的实际长度作为参数,并返回所需字节数,允许调用者在可能的情况下重新分配缓冲区。它已移植到许多操作系统,但最值得注意的是被 glibc 维护者拒绝,他们建议 C 程序员需要跟踪字符串长度,并且“使用此函数只会导致其他错误”。[1]

errno_t strcat_s(char* dst, rsize_t size, const char* src);

strcat_s 函数,在 ISO/IEC TR 24731 中提出标准化。[2][3] 由 Microsoft C 运行时库支持。[4] 以及其他一些 C 库。如果源字符串不适合,它将返回非零,并将缓冲区设置为空字符串(如果原始字符串未存储在其他地方或调用者忽略返回结果,这是一个灾难性的结果)。它也明确不受某些库的支持,包括 GLibc 库。[5] 微软编译器生成的警告消息建议程序员更改strcatstrncat到这个函数,据一些人推测,这是微软试图将开发人员锁定在其平台上的行为。[6][7]

参考文献

[编辑 | 编辑源代码]
  1. libc-alpha 邮件列表,从 2000 年 8 月 8 日的主题中选取的邮件:536061
  2. ISO/IEC. ISO/IEC WDTR 24731 安全 C 库函数规范. 国际标准化组织. 检索于 2008-04-23.
  3. Plakosh, Daniel. "strcpy_s() 和 strcat_s()". Pearson Education, Inc. 检索于 2006-08-12.
  4. Microsoft. "CRT 中的安全增强". MSDN. 检索于 2008-09-16.
  5. "回复:实现“C 库的扩展”(ISO/IEC WG14 N1172)".
  6. Danny Kalev. "他们又来了". InformIT.
  7. "安全增强的 CRT,比标准库更安全?".


[编辑 | 编辑源代码]
华夏公益教科书