3

我的实现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));

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

输出:你好史密斯先生!中止(核心转储)

我做错了什么?

4

3 回答 3

5

您的程序 在运行时进行缓冲区溢出strcat(arr3, arr4),因为arr3大小正好等于"Mr."string 的长度,所以它没有额外的内存空间用于额外的字符(来自arr4)。

的大小arr3应该是 a 的至少字符串长度"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. ";

is的大小arr2= 字符串"Mr."长度 + 1 (1 因为\0) 字符的长度。第一个在第一个 while 循环中将指针strcat()移动temp到指向 null 的位置while(*tmp) ++tmp ;

之后,在第二个 while 循环中,while( (*tmp++ = *src++ ) != '\0') ; 您尝试访问和分配未分配的内存(我将超出您的进程控制)并访问未分配的内存是 C 中未定义的行为。

编辑:

代码 arr3如下图所示,其中temp指向arr3数组:

                arr3

   temp          5   6  7  8    
  +-----+      +--+--+--+---+
  | 5   +----->|M |r |. |\0 |
  +-----+      +--+--+--+---+

当循环while(*tmp) ++tmp ; 中断temp开始指向存储8null\0的内存位置时,如下图所示。

                arr3

   temp          5   6  7  8    
  +-----+      +--+--+--+---+
  | 8   |      |M |r |. |\0 |
  +-----+      +--+--+--+---+
     |                    ^
     +--------------------|

当您temp++ 在循环 中执行时while( (*tmp++ = *src++ ) != '\0') ;temp递增以指向内存位置9及以后,但访问和分配内存910.. 是非法的,因为它没有分配。这会导致操作系统内核向导致异常的进程发送信号核心转储。值得注意的是:当操作系统检测到进程违反内存权限时——对有效内存的无效访问会给出:SIGSEGV 并且对无效地址的访问会给出:SIGBUS)。

程序错误信号:
当这些程序错误信号之一终止进程时,它还会写入一个核心转储文件,该文件记录终止时进程的状态。核心转储文件被命名为“核心”,并写入当时进程中的当前目录中。(在 GNU 系统上,您可以使用环境变量 COREFILE 指定核心转储的文件名。)核心转储文件的目的是让您可以使用调试器检查它们以调查导致错误的原因。

如果您分配额外的内存(如@JerryCoffin 和@Paul R 建议的那样),那么您可以访问超出\0内存位置8)的内存没问题。

注意:如果你在声明时没有给出大小,那么数组的大小将等于字符串的大小,例如char arr3[] = "Mr. ";大小为5. 但是,如果您明确给出大小,char arr3[84] = "Mr. ";则将大小aar384初始内存包含Mr.0所有位置的其余部分中。

在我的解决方案中,我完全分配了与字符串一样大的新内存块,arr3并且arr4可以使用动态内存分配(malloc()函数)与空符号一起存储。此外,如果您使用ptr = malloc()或分配动态内存,ptr = calloc()那么您应该在使用free(ptr).

于 2013-05-25T15:23:22.010 回答
2

您没有分配任何额外的空间,str3因此尝试使用附加字符strcat会溢出分配的存储空间 - 将您的代码更改为例如:

char arr3[80] = "Mr. "; // <<< allocate additional storage for appending more characters
char arr4[] = "Smith";
printf("Hello %s!", strcat(arr3, arr4));
于 2013-05-25T15:22:46.980 回答
1

问题不在于您的strcat,而在于您如何使用/调用它。您正在写超过目标数组的末尾。

换成arr3类似的东西char arr3[32] = "Mr. ";,一切都会好起来的。

于 2013-05-25T15:23:22.917 回答