strcat()实现有效,但最后导致核心转储
我的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)
执行缓冲区溢出 ,因为strcat(arr3, arr4)
大小等于"Mr."
长度 字符串,它没有额外的内存空间用于额外的字符(来自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
核心转储的原因:
在你的代码中:
char arr3[] = "Mr. ";
arr2
的大小是=字符串"Mr."
长度 长度+ 1
(1因为\0
)字符。 strcat()
首先将temp
指针移动到第一个while循环中的null, while(*tmp) ++tmp ;
。
之后在第二个while while while( (*tmp++ = *src++ ) != '\0') ;
您正在尝试访问和分配未分配的内存(我的进程控制之外)和访问未分配的内存是C中未定义的行为。
编辑:
在代码中, arr3
类似于下图,其中temp
指向arr3
数组:
arr3 temp 5 6 7 8 +-----+ +--+--+--+---+ | 5 +----->|M |r |. |\0 | +-----+ +--+--+--+---+
while while(*tmp) ++tmp ;
break temp
指向内存位置8
,其中存储了null \0
,如下图所示。
arr3 temp 5 6 7 8 +-----+ +--+--+--+---+ | 8 | |M |r |. |\0 | +-----+ +--+--+--+---+ | ^ +--------------------|
当你在循环中执行temp++
while( (*tmp++ = *src++ ) != '\0') ;
, temp
增量指向内存位置9
及以后,但在内存9
上访问和分配是非法的,因为它没有分配。 这会导致OS内核向您的进程发送信号核心转储 ,从而导致exception。 ( 有趣的是:因为OS检测到进程的内存权限违规 – 对有效内存的无效访问给出:SIGSEGV并且访问无效地址给出:SIGBUS)。
程序错误信号:
当其中一个程序错误信号终止进程时,它还会写入一个核心转储文件,该文件在终止时记录进程的状态。 核心转储文件名为“core”,并且写入当时进程中当前的任何目录。 (在GNU系统上,您可以使用环境变量COREFILE指定核心转储的文件名。)核心转储文件的目的是让您可以使用调试器检查它们以调查导致错误的原因。
如果你分配额外的内存(如@JerryCoffin和@Paul R建议的那样)那么你可以访问超出\0
( 内存位置8
)的内存是没有问题的。
注意:如果你没有在声明时给出大小,那么数组的大小将等于字符串的大小,例如在char arr3[] = "Mr. ";
大小是5
。 但是,如果你明确给出大小char arr3[84] = "Mr. ";
那么aar3
大小将是84
,初始内存包含Mr.
然后在其余所有位置包含0
。
在我的解决方案中,我完全分配了新的内存块,这些内存块与字符串arr4
和arr4
一样大,可以使用动态内存分配( malloc()
函数)与空符号一起存储。 另外如果使用ptr = malloc()
或ptr = calloc()
分配动态内存,那么当使用free(ptr)
完成工作时,应该显式释放内存。
你没有在str3
分配任何额外的空间,所以尝试使用strcat
追加字符将溢出分配的存储 – 将代码更改为:
char arr3[80] = "Mr. "; // <<< allocate additional storage for appending more characters char arr4[] = "Smith"; printf("Hello %s!", strcat(arr3, arr4));
问题不在于你的strcat
,而在于你如何使用/调用它。 你正在写目标数组的末尾。
将arr3
更改为char arr3[32] = "Mr. ";
一切都会好的。