我对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));
它实际上连接了两个字符串并将其打印出来但仍导致核心转储。
输出:你好史密斯先生!流产(核心倾销)
我做错了什么?
答案 0 :(得分:4)
您的程序在运行时buffer overflow执行strcat(arr3, arr4)
,因为arr3
大小等于"Mr."
字符串的长度,它没有额外的内存空间用于额外的字符(来自arr4
)。
arr3
的大小应该是"Mr. " + "Smith" + 1
的最小字符串长度
( extra 1 for string termination \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
的长度(因为\0
)字符占1。 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)。
Program Error Signals:
当其中一个程序错误信号终止一个过程时,它也会 写一个核心转储文件,记录进程的状态 终止时间。核心转储文件名为`core'并被编写 在当时进程中的当前目录中。 (关于 在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)
完成工作时应明确释放内存。
答案 1 :(得分:2)
您尚未在str3
中分配任何额外空间,因此尝试使用strcat
追加字符会溢出已分配的存储空间 - 将您的代码更改为例如:
char arr3[80] = "Mr. "; // <<< allocate additional storage for appending more characters
char arr4[] = "Smith";
printf("Hello %s!", strcat(arr3, arr4));
答案 2 :(得分:1)
问题不在于您的strcat
,而在于您如何使用/调用它。你正在写目标数组的末尾。
将arr3
更改为char arr3[32] = "Mr. ";
之类的内容,一切顺利。