c - 使用清除内存违规中止而不是段错误

标签 c memory-management

我在处理 C 字符串时遇到了这种奇怪的行为。这是 K&R 书中的一个练习,我应该在其中编写一个函数,将一个字符串附加到另一个字符串的末尾。这显然需要目标字符串分配足够的内存,以便源字符串适合。这是代码:

 /* strcat: Copies contents of source at the end of dest */
 char *strcat(char *dest, const char* source) {
  char *d = dest;
  // Move to the end of dest
  while (*dest != '\0') {
    dest++;
  } // *dest is now '\0'

  while (*source != '\0') {
    *dest++ = *source++;
  }
  *dest = '\0';
  return d;
}

在测试期间,我写了以下内容,预计程序运行时会发生段错误:

int main() {
  char s1[] = "hello";
  char s2[] = "eheheheheheh"; 
  printf("%s\n", strcat(s1, s2));
}

据我所知,s1 分配了一个包含 6 个 chars 的数组,s2 分配了一个包含 13 个 chars 的数组。我认为当 strcat 尝试写入索引高于 6 的 s1 时,程序会出现段错误。相反,一切正常,但程序没有干净地退出,而是:

helloeheheheheheh
zsh: abort      ./a.out

并以代码 134 退出,我认为这只是中止的意思。

为什么我没有收到段错误(或者如果字符串分配在堆栈上则覆盖 s2)?这些字符串在内存中的什么位置(堆栈或堆)?

感谢您的帮助。

最佳答案

I thought that when strcat tries to write to s1 at indexes higher than 6 the program would segfault.

在堆栈上分配的内存边界之外写入是 undefined behaviour .调用此未定义的行为通常(但不总是)会导致段错误。 但是,您不能确定会发生段错误。

维基百科链接解释得很好:

When an instance of undefined behavior occurs, so far as the language specification is concerned anything could happen, maybe nothing at all.

因此,在这种情况下,您可能会遇到段错误,程序可能会中止,或者有时它可以正常运行。或者,任何东西。无法保证结果。

Where are these strings in memory (the stack, or the heap)?

由于您在 main() 中将它们声明为 char [],因此它们是具有 automatic storage 的数组,出于实际目的,这意味着它们在堆栈上。

关于c - 使用清除内存违规中止而不是段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17983561/

相关文章:

c - C 编程语言教科书 Joy of C 中的 "grading"练习问题

C 内存缓冲区破坏微 Controller 内存分配 - Atmel ATxmega

c++ - 这是将 CString 与堆还是堆栈一起使用?我如何将它与堆内存一起使用?

c++ - 我应该返回对堆对象的引用还是返回值?

c - 具有 4 Gb RAM 和 10 Gb 交换分区的 32 位内核中的无限循环 malloc

c - 从字符串中提取字符串

c++ - 我可以要求用户重新输入命令行参数吗

c++ - 如何告诉 valgrind 对 fork 进程进行 memcheck?

Java - 是否有一种线程安全的方式来分配新对象而无需锁?

Java固定内存映射