我的实现strcat(char*, const char*)似乎有效,但随后会导致核心转储。
strcat() 执行:
char* strcat(char* dest, const char* src)
{
char* tmp = dest;
while(*tmp) ++tmp ;
while( (*tmp++ = *src++ ) != '\0') ;
return (dest);
}
Run Code Online (Sandbox Code Playgroud)
代码在int main()那里我打电话的strcat():
char arr3[] = "Mr. ";
char arr4[] = "Smith";
printf("Hello %s!", strcat(arr3, arr4));
Run Code Online (Sandbox Code Playgroud)
它实际上连接了两个字符串并将其打印出来,但仍然导致核心转储。
输出:你好,史密斯先生!中止(核心转储)
我做错了什么?
您的程序 在运行时执行缓冲区溢出,strcat(arr3, arr4)因为arr3size 仅等于"Mr."string 的长度,因此它没有用于额外字符(来自arr4)的额外内存空间。
大小arr3应该是 a 的至少字符串长度"Mr. " + "Smith" + 1
(字符串终止\0字符额外 1)
我的建议是使用动态内存分配以获得足够大小的缓冲区,执行如下代码:
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
Run Code Online (Sandbox Code Playgroud)
Core-Dump的原因:
在您的代码中:
char arr3[] = "Mr. ";
Run Code Online (Sandbox Code Playgroud)
的大小arr2是 = 字符串"Mr."长度 + 1 (1 因为\0) 字符的长度。第strcat()一个将temp指针移动到第一个 while 循环中的 null 点while(*tmp) ++tmp ;。
在那之后,在第二个 while 循环中,while( (*tmp++ = *src++ ) != '\0') ; 您尝试访问和分配未分配的内存(我不受您的进程控制)并访问您尚未分配的内存是 C 中的未定义行为。
编辑:
在代码 arr3中类似于下图,其中temp指向arr3数组:
arr3
temp 5 6 7 8
+-----+ +--+--+--+---+
| 5 +----->|M |r |. |\0 |
+-----+ +--+--+--+---+
Run Code Online (Sandbox Code Playgroud)
当循环while(*tmp) ++tmp ; 中断temp开始指向存储8空值的内存位置时\0,如下图所示。
arr3
temp 5 6 7 8
+-----+ +--+--+--+---+
| 8 | |M |r |. |\0 |
+-----+ +--+--+--+---+
| ^
+--------------------|
Run Code Online (Sandbox Code Playgroud)
当你temp++ 在循环 while( (*tmp++ = *src++ ) != '\0') ;,temp增量指向的内存位置9,并起,但访问和内存分配9,10..因为它不是分配是非法的。这会导致操作系统内核向导致异常的进程发送信号核心转储。(有趣的是:当操作系统检测到进程的内存权利冲突时——对有效内存的无效访问给出:SIGSEGV 而对无效地址的访问给出:SIGBUS)。
程序错误信号:
当这些程序错误信号之一终止进程时,它还会写入一个核心转储文件,该文件记录终止时进程的状态。核心转储文件被命名为“核心”,并写入当时进程中的任何当前目录。(在 GNU 系统上,您可以使用环境变量 COREFILE 指定核心转储的文件名。)核心转储文件的目的是让您可以使用调试器检查它们以调查导致错误的原因。
如果您分配额外的内存(如@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).