#memory #memory-leaks #allocation #mocking #leak

dev mockalloc

一个允许测试使用全局分配器的代码的crate

3个版本

0.1.2 2020年11月18日
0.1.1 2020年11月14日
0.1.0 2020年11月14日

内存管理中排名第184位

Download history 3/week @ 2023-12-04 1/week @ 2023-12-18 6/week @ 2023-12-25 22/week @ 2024-01-01 18/week @ 2024-01-08 24/week @ 2024-01-15 6/week @ 2024-01-22 30/week @ 2024-02-12 18/week @ 2024-02-19 65/week @ 2024-02-26 24/week @ 2024-03-04 24/week @ 2024-03-11 15/week @ 2024-03-18

每月下载次数131
5 crate使用

MIT/Apache

41KB
733

mockalloc

Mockalloc是一个允许测试使用全局分配器的代码的crate。它使用概率算法来检测和区分多种分配相关错误

  • 内存泄漏
  • 重复释放
  • 无效释放(坏指针)
  • 无效释放(坏大小)
  • 无效释放(坏对齐)

使用方法

典型使用涉及在测试期间启用Mockalloc分配器,例如

#[cfg(test)]
mod tests {
    use std::alloc::System;
    use mockalloc::Mockalloc;

    #[global_allocator]
    static ALLOCATOR: Mockalloc<System> = Mockalloc(System);
}

启用分配器后,有几种方法可以在测试中使用它。

最简单的方法是在测试上使用#[mockalloc::test]属性,而不是常用的#[test]属性

    #[mockalloc::test]
    fn it_works() {
        // Some code which uses the allocator
    }

如果检测到上述任何分配错误,测试将失败。如果未检测到分配,则测试将因NoData错误而失败,以确保Mockalloc分配器处于活动状态。

您还可以使用mockalloc来测试代码的特定部分是否存在内存问题,而无需检查整个测试,可以使用assert_allocs函数。

前面示例中的#[mockalloc::test]属性只是

    #[test]
    fn it_works() {
        mockalloc::assert_allocs(|| {
            // Some code which uses the allocator
        });
    }

您还可以进行更详细的断言:例如,您可能希望断言某段代码执行了特定数量的分配。为此,您可以使用record_allocs函数

    #[test]
    fn it_works() {
        let alloc_info = mockalloc::record_allocs(|| {
            // Some code which uses the allocator
        });

        assert_eq!(alloc_info.num_allocs(), 2);

        // This is what `assert_allocs` does internally:
        alloc_info.result().unwrap()
    }

限制

每个线程的分配都单独跟踪。这允许并行运行测试,但也意味着如果某个线程分配的指针在稍后被另一个线程释放,则库会报告假阳性。

该算法无法检测到错误的具体位置,它只能指示存在哪种类型的错误。

它的工作原理

分配器不分配任何内存来跟踪。它使用一种概率算法,通过散列分配和释放的各种元数据,然后使用交换律操作累加这些元数据,以保证顺序不影响结果。

根据测试区域结束时哪个累加器返回零,可以区分不同的分配错误。

以下元数据被散列并累加

  • 指针
  • 大小 & 指针
  • 对齐 & 指针

除了跟踪分配和释放的总数。

我们可以通过查看分配和释放的总数之间的差异来检测内存泄漏和双重释放。

否则,如果指针累加器没有返回零,我们知道释放了一个无效的指针。

否则,我们知道释放了正确的指针,但可能大小和/或对齐不正确,我们可以通过其他两个累加器检测到这一点。

如果所有累加器都返回零,那么我们知道一切正常。

每个累加器和散列都是128位,以基本消除冲突的机会。

依赖项

~1.1–2MB
~44K SLoC