【问题标题】:Ensuring out-of-bound memory writes trigger an immediate fault确保越界内存写入会立即触发故障
【发布时间】:2013-08-06 19:28:21
【问题描述】:

我很难跟踪一个与内存分配有关的非常典型的 C 错误。我的一个缓冲区太短了一个字节。结果,一个字节的写入量超出了上限。

在大多数情况下,它没有效果;但在某些特定情况下,它会导致未来的操作失败(通常是 malloc,或另一个函数中的隐藏 malloc)。

使此类错误难以跟踪的原因是它们不会发生在错误所在的位置,从而导致初始诊断错误。而且它在调试模式下也永远不会发生,这使得搜索变得更加困难。

这种错误在 C 中很常见,并且是该语言长期存在的弱点。

那么有什么可以帮助的呢?

好吧,如果“一个字节太多”写入触发立即故障,它确实会有所帮助,首先要检测问题出在哪里,还要检测到是否有问题! (在前面的示例中,错误通过了所有测试并进入了生产阶段;噩梦般的情况......)。

这样的设置是否存在(在 C 中)? 我猜如果存在某种解决方案,它可能取决于平台。不过当然,如果有便携的,我就更感兴趣了。

[编辑] 感谢您提供非常好的答案。我看到没有灵丹妙药的解决方案,而是一套减轻问题的工具。我需要一些时间来研究您答案中提供的所有非常好的链接。

【问题讨论】:

    标签: c memory-leaks malloc


    【解决方案1】:

    用法线触发立即故障可能很困难。不过有alternatives 可以解决这个问题。我最喜欢的是在valgrind下运行程序:任何有趣的事情都会被标记为非法读取或非法写入。

    这是一个简单的错误程序:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void)
    {
        char *p = malloc(10);
        p[10] = 42;
    
        return 0;
    }
    

    这是我在 valgrind 下运行时得到的结果:

    ==11551== Invalid write of size 1
    ==11551==    at 0x40052A: main (main.c:7) # <------ compile with debugging symbols
    ==11551==  Address 0x51b904a is 0 bytes after a block of size 10 alloc'd
    ==11551==    at 0x4C28BED: malloc (vg_replace_malloc.c:263)
    ==11551==    by 0x40051D: main (main.c:6)
    ==11551== 
    

    任何侵入性较小的东西都可能具有较小的粒度(即它可能会错过一些非法访问)。我链接的 wiki 页面有很多适用于各种平台的替代方案。

    【讨论】:

    • 我读过很多关于 valgrind 的优秀 cmets。但我可以看到的问题之一是它似乎不支持 Windows。如果要调试的程序是 Windows 相关的怎么办?
    • @Cyan 那么你必须获得另一个(可能是商业的)程序。我认为 IBM Rational Purify 可以做到这一点。
    【解决方案2】:

    你可以使用 gcc 的-Wstack-protector。对于调试,您可以使用mudflap

    【讨论】:

    • 好点,我不知道挡泥板。但我猜它不适用于 GCC for MinGW ?
    【解决方案3】:

    有一些工具可以在缓冲区之后写入“红色区域”区域。红色区域将包含一个特殊的关键字,可以定期检查(例如在空闲时间、使用时间等)以确定缓冲区的健全性。这只会告诉你是否有问题......而不是是谁做的。

    另一种解决方案是在缓冲区之后立即对页面进行“页面保护”。例如,

    vaddr = mmap(2 pages); // buffer of 1 page, red zone 1 page
    mprotect(vaddr+1 page, READ_ONLY);
    

    这将捕获对红色区域页面的任何写访问权限,并有助于当场抓住罪魁祸首。当然,afaik,mprotect() 需要一个映射地址,粒度为 1 页。

    【讨论】:

      猜你喜欢
      • 2015-01-31
      • 1970-01-01
      • 1970-01-01
      • 2013-09-09
      • 1970-01-01
      • 1970-01-01
      • 2018-08-20
      • 2018-06-23
      • 1970-01-01
      相关资源
      最近更新 更多