我的 strcat(char*, const char*) 实现似乎有效,但随后会导致核心转储。
strcat() 实现:

char* strcat(char* dest, const char* src)
{
    char* tmp = dest;
    while(*tmp) ++tmp ;
    while( (*tmp++ = *src++ ) != '\0') ;
    return (dest);
}

int main() 中调用 strcat() 的代码:
char arr3[] = "Mr. ";
char arr4[] = "Smith";
printf("Hello %s!", strcat(arr3, arr4));

它实际上连接了两个字符串并将其打印出来,但仍然导致核心转储。

输出: 你好,史密斯先生!中止(核心转储)

我做错了什么?

最佳答案

您的程序在运行时通过 strcat(arr3, arr4) 执行 buffer overflow ,因为 arr3 大小正好等于 "Mr." string 的长度,它没有用于额外字符的额外内存空间(来自 arr4 )。
arr3 的大小应该是 "Mr. " + "Smith" + 1 的至少字符串长度
(额外 1 用于字符串终止 \0 字符)

我的建议是使用动态内存分配以获得足够大小的缓冲区,执行如下代码:

char arr3[] = "Mr. ";
char arr4[] = "Smith";
length = strlen(arr3) + strlen(arr4) + 1;  //cal-length (sufficient long buffer)
char* new_arr = malloc(length);  // allocate memory
strcpy(new_arr, arr3);  // copy first string
strcat(new_arr, arr4);  // then check your function to concat strings

Core-Dump 的原因:

在您的代码中:
char arr3[] = "Mr. ";
arr2 的大小是 = 字符串长度 "Mr." 长度 + 1 (1 因为 \0 )字符。 strcat() 首先将 temp 指针移动到第一个 while 循环 while(*tmp) ++tmp ; 中指向 null。

在第二个 while 循环 while( (*tmp++ = *src++ ) != '\0') ; 之后,您尝试访问和分配未分配的内存(我不在您的进程控制范围内)并访问您未分配的内存是 C 中的未定义行为。

编辑:

在代码中 arr3 类似于下图中,其中 temp 指向 arr3 数组:
                arr3

   temp          5   6  7  8
  +-----+      +--+--+--+---+
  | 5   +----->|M |r |. |\0 |
  +-----+      +--+--+--+---+

当循环 while(*tmp) ++tmp ; 中断时,temp 开始指向存储空 8 的内存位置 \0,如下图所示。
                arr3

   temp          5   6  7  8
  +-----+      +--+--+--+---+
  | 8   |      |M |r |. |\0 |
  +-----+      +--+--+--+---+
     |                    ^
     +--------------------|

当您在循环 temp++ 中执行 while( (*tmp++ = *src++ ) != '\0') ; 时,temp 递增以指向内存位置 9 及以后,但访问和分配内存 910 .. 是非法的,因为它没有分配。这会导致操作系统内核向导致异常的进程发送信号 core dump 。 ( 有趣的是: 因为操作系统检测到进程的内存权利冲突——对有效内存的无效访问给出:SIGSEGV 而对无效地址的访问给出:SIGBUS)。



如果您分配额外的内存(如@JerryCoffin 和@Paul R 建议的那样),那么您可以访问超出 \0 (内存位置 8 )的内存没问题。

注意: 如果你没有在声明时给出大小,那么数组的大小将等于字符串的大小,例如在 char arr3[] = "Mr. "; 大小是 5 。但是,如果您将大小明确指定为 char arr3[84] = "Mr. ";,那么 aar3 的大小将是 84,并且初始内存包含 Mr.,然后在所有位置的其余部分包含 0

在我的解决方案中,我完全分配了与字符串 arr3arr4 一样大的新内存块,可以使用动态内存分配( malloc() 函数)用空符号存储。此外,如果您使用 ptr = malloc()ptr = calloc() 分配动态内存,那么您应该在使用 free(ptr) 完成工作时明确释放内存。

关于c - strcat() 实现有效,但最终会导致核心转储,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16750998/

10-12 05:52