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

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

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

输出: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 及以后,但访问和分配内存 910.. 是非法的,因为它没有分配。这导致操作系统内核发送信号 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 在其余所有位置。

在我的解决方案中,我完全分配了与字符串 arr3arr4 一样大的新内存块,可以使用动态内存分配( malloc() 函数)。此外,如果您使用 ptr = malloc()ptr = calloc() 分配动态内存,那么您应该在使用 free(ptr)< 完成工作时显式释放内存.

关于c - strcat() 实现有效,但最后导致核心转储,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16750998/

相关文章:

c - strcat 生成崩溃程序 (0xc0000005)

c - C语言编程中的strcat()

c - 如何根据成员的值对结构实例进行排序

c - 尝试使用重新定义函数名称的 header 构建程序时出现“未定义的函数引用”

c - 获取 "segmentation fault core dump"

c++ - 是否可能导致多进程休眠(核心转储?)?

c - 结构到字符串 - strcat 不工作

c - 提示用户在 C 中再次播放

c++ - 在 x + y 中获取 "carry"

linux - 如何从 coredump 文件中提取 AT_EXECFN