strcat()实现有效,但最后导致核心转储

时间:2013-05-25 15:21:01

标签: c coredump 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));

它实际上连接了两个字符串并将其打印出来但仍导致核心转储。

输出:你好史密斯先生!流产(核心倾销)

我做错了什么?

3 个答案:

答案 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及之后,但访问和分配内存910 ..是非法的,因为它没有分配。这会导致操作系统内核向您的进程发送信号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

在我的解决方案中,我完全分配了新的内存块,这些内存块与字符串arr3arr4一样大,可以使用动态内存分配(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. ";之类的内容,一切顺利。