我的 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
及以后,但访问和分配内存 9
、 10
.. 是非法的,因为它没有分配。这会导致操作系统内核向导致异常的进程发送信号 core dump 。 ( 有趣的是: 因为操作系统检测到进程的内存权利冲突——对有效内存的无效访问给出:SIGSEGV 而对无效地址的访问给出:SIGBUS)。如果您分配额外的内存(如@JerryCoffin 和@Paul R 建议的那样),那么您可以访问超出
\0
(内存位置 8
)的内存没问题。注意: 如果你没有在声明时给出大小,那么数组的大小将等于字符串的大小,例如在
char arr3[] = "Mr. ";
大小是 5
。但是,如果您将大小明确指定为 char arr3[84] = "Mr. ";
,那么 aar3
的大小将是 84
,并且初始内存包含 Mr.
,然后在所有位置的其余部分包含 0
。在我的解决方案中,我完全分配了与字符串
arr3
和 arr4
一样大的新内存块,可以使用动态内存分配( malloc()
函数)用空符号存储。此外,如果您使用 ptr = malloc()
或 ptr = calloc()
分配动态内存,那么您应该在使用 free(ptr)
完成工作时明确释放内存。关于c - strcat() 实现有效,但最终会导致核心转储,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16750998/