22 个版本

0.6.3 2023 年 3 月 22 日
0.6.1 2022 年 4 月 25 日
0.6.0 2021 年 8 月 27 日
0.5.7 2021 年 1 月 15 日
0.5.6 2020 年 1 月 20 日

#40内存管理

Download history 1417/week @ 2024-03-25 1425/week @ 2024-04-01 653/week @ 2024-04-08 1069/week @ 2024-04-15 806/week @ 2024-04-22 1600/week @ 2024-04-29 1021/week @ 2024-05-06 951/week @ 2024-05-13 1026/week @ 2024-05-20 1042/week @ 2024-05-27 1421/week @ 2024-06-03 3195/week @ 2024-06-10 1548/week @ 2024-06-17 794/week @ 2024-06-24 702/week @ 2024-07-01 1002/week @ 2024-07-08

4,083 每月下载量
5 crate 中使用

MIT/Apache

62KB
831

checkers

github crates.io docs.rs build status

Checkers 是一个简单的 Rust 分配清理器。它通过全局分配器进行连接,可以在集成测试期间对不安全的 Rust 进行合理性检查。由于它通过全局分配器连接,因此不需要任何额外的依赖项,并且适用于所有平台 - 但它可以在验证方面更加有限。

它可以检查以下内容

  • 双重释放。
  • 内存泄漏。
  • 释放未分配的区域。
  • 释放已分配区域的部分。
  • 释放与不匹配的布局的区域。
  • 底层分配器生成的区域遵循请求的布局。即大小和对齐。
  • 内存使用情况的详细信息。
  • 其他用户定义的条件(《测试》中查看)。

它不能做什么

  • 测试多线程代码。由于分配器是全局的,因此难以对每个测试用例的范围进行划分。
  • 检测越界访问。

使用方法

checkers 作为项目中的 dev-dependency 添加

checkers = "0.6.2"

在一个 测试文件 中替换全局分配器,并使用 #[checkers::test] 将要内存清理的测试用例包装起来

#[global_allocator]
static ALLOCATOR: checkers::Allocator = checkers::Allocator::system();

#[checkers::test]
fn test_allocations() {
    let _ = Box::into_raw(Box::new(42));
}

请注意,您必须将测试用例编写为 集成测试,将其添加到您的 tests/ 文件夹中,以便隔离全局分配器的使用。


安全性

默认功能集下,此库执行诊断会产生不确定的行为。因此,建议您只使用检查器进行测试,而绝对不要在生产代码中使用。

如果您想避免这种情况,您将不得不禁用realloczeroed功能,但这也会产生更少有操作性的诊断。

在未来的版本中,这种行为将通过功能标志进行选择,而不是默认启用。


功能

以下是可以用的功能,它们会改变检查器的工作方式。

  • realloc - 启用此功能会导致检查器验证realloc操作是否正确实现。即旧区域的字节被忠实地传输到新的、调整大小的区域。由于这可能会产生相当大的性能影响,因此可以禁用它。请注意,这将通过读取未初始化的内存产生不确定的行为(#1),并且仅应启用以在最佳努力的基础上提供诊断。
  • zeroed - 启用此功能会导致检查器验证对alloc_zeroed的调用产生所有字节都被设置为零的区域。请注意,如果底层分配器实现得不好,这将产生不确定的行为(#1),因为它可能会读取未初始化的内存。
  • macros - 启用宏的依赖和重新导出,如#[checkers::test]
  • backtrace - 启用捕获和渲染回溯。如果禁用,则任何包含回溯的字段都将为None

示例

建议您使用检查器进行集成测试,这些测试默认位于./tests目录中。此目录中的每个文件都将作为一个单独的程序编译,因此可以使用全局分配器进行更隔离的使用。

然后,我们在将checkers::Allocator作为全局分配器安装后,可以在测试中使用#[checkers::test]属性宏或checkers::with函数。

#[global_allocator]
static ALLOCATOR: checkers::Allocator = checkers::Allocator::system();

#[checkers::test]
fn test_allocations() {
    let _ = Box::into_raw(Box::new(42));
}

上述代码将产生以下测试输出

dangling region: 0x226e5784f30-0x226e5784f40 (size: 16, align: 8).
thread 'test_leak_box' panicked at 'allocation checks failed', tests\leaky_tests.rs:4:1

使用checkers::with,我们可以执行更详细的诊断

#[global_allocator]
static ALLOCATOR: checkers::Allocator = checkers::Allocator::system();

#[test]
fn test_event_inspection() {
    let snapshot = checkers::with(|| {
        let _ = vec![1, 2, 3, 4];
    });

    assert_eq!(2, snapshot.events.len());
    assert!(snapshot.events[0].is_alloc_with(|r| r.size >= 16));
    assert!(snapshot.events[1].is_free_with(|a| a.size >= 16));
    assert_eq!(1, snapshot.events.allocs());
    assert_eq!(1, snapshot.events.frees());
    assert!(snapshot.events.max_memory_used().unwrap() >= 16);
}

依赖关系

~0–770KB
~16K SLoC