【问题标题】:In precisely which scenarios does C throw a segmentation fault?C 究竟在哪些情况下会引发分段错误?
【发布时间】:2020-02-20 08:37:24
【问题描述】:

我知道在越界访问数组的情况下:

int arr[2]; 
arr[3] = 10;

C 会在运行时抛出一个Segmentation fault (core dumped)

但是,C 不会使用其他内容(例如 strcpy())检查越界访问。

我想确切地知道哪些情况会导致分段错误,哪些情况不会。

【问题讨论】:

标签: c segmentation-fault coredump


【解决方案1】:

访问您不拥有的任何内存都是未定义的行为。这仅仅意味着 C 标准根本不需要编译器提供任何东西来处理这种情况。

由于 C 努力成为一种高效的语言,编译器很少(曾经?)会发布机器代码来提供对此类事物的运行时检查。如果在编译时可以检测到违规,它们可能会也可能不会发出警告或错误。

其本质是:您在运行时收到的任何错误消息(包括段错误)通常来自操作系统。在较旧的系统/操作系统上,甚至今天在较小的(嵌入式)系统上,这种内存管理是/不可用的,并且内存访问违规可能会使您的整个系统崩溃,可能在最初的违规发生后很长时间。或者什么都不会发生。甚至更隐蔽的事情,例如数据损坏。

因此,很高兴拥有现代操作系统的虚拟内存管理系统的安全网,但不要依赖它们来防止编程错误造成更大的损害,或者首先检测到此类错误。

您还应该尝试使用 valgrind 等工具,这些工具可为您的程序提供大量运行时分析和错误检测;通过这种方式可以学到很多东西。

顺便说一句:正如 selbie 在评论中指出的那样,您的代码可能会覆盖函数的堆栈帧或激活记录的一部分。原因是大多数机器上的堆栈向下增长(新内存分配在较小的地址),但数组索引向上移动。许多编译器包括使用“堆栈金丝雀”进行编译的选项,该选项可以在运行时检测堆栈损坏。这是在开发和测试期间非常有用的功能,并且还提供了一些防御恶意软件试图完全利用这种缓冲区溢出。

【讨论】:

    【解决方案2】:

    我想通了。仅当我们访问操作系统未分配给进程的内存时才会发生分段错误。但有时,在越界访问时,我们可能仍然在整个程序的分配内存中,因此不会给我们带来分段错误 - 在这种情况下它会给出垃圾值。

    【讨论】:

    • 问题中的示例导致段错误的原因是因为您可能会破坏堆栈。函数返回时发生崩溃。如果您使用 malloc 分配该数组,然后插入一个超出范围的值,则不能始终保证您会可靠地遇到 seg 错误。
    猜你喜欢
    • 1970-01-01
    • 2020-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-10
    • 1970-01-01
    • 1970-01-01
    • 2021-03-05
    相关资源
    最近更新 更多