【问题标题】:Why does running this not issue a segmentation fault? [duplicate]为什么运行它不会发出分段错误? [复制]
【发布时间】:2012-01-01 21:55:29
【问题描述】:

可能重复:
Invalid read/write sometimes creates segmentation fault and sometimes does not

我有以下代码:

#include <stdlib.h>
#include <stdio.h>

int main() {
    int *ptr = NULL;
    ptr = malloc(sizeof(char));
    if (ptr) {
        *ptr = 10;
        printf("sizeof(int): %zu\nsizeof(char): %zu\n", sizeof(int), sizeof(char));
        printf("deref of ptr: %d\n", *ptr);
        free(ptr);
        return EXIT_SUCCESS;
    }
    else
        return EXIT_FAILURE;
}

当我编译并运行它时,我得到以下输出:

$ gcc test.c
$ ./a.out 
sizeof(int): 4
sizeof(char): 1
deref of ptr: 10

sizeof(char) 小于sizeof(int)。我的malloc 调用只为char 留出了足够的空间。然而,我的程序能够为ptr 分配一个整数值而不会崩溃。为什么会这样?

【问题讨论】:

  • 您可能希望查看此问题及其答案以获得指导:stackoverflow.com/questions/8641478/…
  • C 不一定会尊重变量“边界”,因此您可能会覆盖内存中的一些随机 3 字节,这些字节恰好跟随您分配的字节。
  • sizeof(char) 始终为 1(6.5.3.4,§3)。
  • 调用未定义行为的美妙之处在于,任何事情都可能发生,而且“没问题”——所需的行为是未定义的。
  • 如果您有答案,如果您尝试将它们添加为答案而不是 cmets,我将不胜感激。

标签: c memory gcc malloc


【解决方案1】:

仅仅因为您正在写入未分配的内存并不意味着程序会崩溃。没有像这样的运行时边界检查。

当您访问的内存超出硬件检测到的操作系统分配的地址范围时,将发生段错误。在此之前,您可能会在堆中获得大量内存访问。

【讨论】:

    【解决方案2】:

    写入太小的缓冲区是未定义的行为。无法保证它会崩溃。它可能不会崩溃。它可能看起来有效。它也可能默默地破坏一些数据。它可能会导致您的程序做一些意想不到的事情 - 当攻击者将未定义行为的影响操纵成不受欢迎的事情时,许多安全漏洞就来自于此。严格解读一个标准,这甚至可能有从你的鼻子召唤恶魔的效果。

    在架构级别上,通常分配会四舍五入到 2 的某个幂(但无论如何都不能保证这一点!),因此您在这里没有看到任何明显不愉快的地方。但是不要依赖这个,因为它可以而且确实会有所不同。

    【讨论】:

      【解决方案3】:

      malloc 实现可以并且通常会分配比您要求的更多的内存。大多数实现至少会四舍五入到最接近的 8 或 16 个字节的倍数。

      【讨论】:

        【解决方案4】:

        硬件内存管理器控制完整的内存页面,通常是 4K。除非您的写入溢出页面边界,否则内存管理硬件不会产生 SEGFAULT/Access Violation 中断。

        您的示例“有效”,因为大量“未定义行为”中的一个元素是“至少目前看来可以正常工作”。如果您为您的应用增加复杂性,该集合的其他成员将出现...

        【讨论】:

          【解决方案5】:

          这是偶然的。您的 malloc 可能分配的块明显大于单个字符(通常是因为跟踪纳米级片段不值得开销)。因此,您可能会超出您应该拥有的空间,但这在您的实施中并不重要。

          根据标准,我认为您的程序仍然是错误的。如果它更大,并且你在它没有意外工作的地方犯了那个错误,你会得到各种不良行为,有时是非法的内存访问,但有时只是完全疯狂的行为,因为你可能会损坏你的或系统数据结构。

          我们的CheckPointer 测试工具应该能够发现这个错误;从技术上讲,您存储在您请求的区域之外,并且通过足够的努力可以检测到。

          【讨论】:

            猜你喜欢
            • 2020-02-27
            • 1970-01-01
            • 2021-11-06
            • 1970-01-01
            • 2011-04-23
            相关资源
            最近更新 更多