我对 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));
它实际上连接了两个字符串并将其打印出来,但仍然导致核心转储。
输出:Hello Mr. Smith!Aborted (core dumped)
我做错了什么?
最佳答案
你的程序正在做 buffer overflow在运行时,通过 strcat(arr3, arr4)
因为 arr3
大小刚好等于 "Mr."
string 的长度,所以它没有额外字符的额外内存空间(来自 arr4
)。
arr3
的大小应该是 "Mr. "+ "Smith"+ 1
的最小字符串长度
(额外 1 用于字符串终止 \0
char)
我的建议是使用动态内存分配以获得足够大小的缓冲区,执行如下代码:
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
核心转储原因:
在你的代码中:
char arr3[] = "Mr. ";
arr2
的大小 = 字符串 "Mr."
的长度 + 1
(1 因为 \0
) 字符。 strcat()
首先在第一个 while 循环 while(*tmp)++tmp ;
中移动 temp
指针指向 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
where null \0
被存储,如下图所示。
arr3
temp 5 6 7 8
+-----+ +--+--+--+---+
| 8 | |M |r |. |\0 |
+-----+ +--+--+--+---+
| ^
+--------------------|
当你在循环 while( (*tmp++ = *src++ ) != '\0') ;
中执行 temp++
时,temp
递增指向内存位置 9
及以后,但访问和分配内存 9
、10
.. 是非法的,因为它没有分配。这导致操作系统内核发送信号 core dump到导致异常的过程。 (值得注意的是:当操作系统检测到进程违反内存权限时——对有效内存的无效访问给出:SIGSEGV 而对无效地址的访问给出:SIGBUS)。
Program Error Signals:
When one of these program error signals terminates a process, it also writes a core dump file which records the state of the process at the time of termination. The core dump file is named `core' and is written in whichever directory is current in the process at the time. (On the GNU system, you can specify the file name for core dumps with the environment variable COREFILE.) The purpose of core dump files is so that you can examine them with a debugger to investigate what caused the error.
如果您分配额外的内存(如@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/