#memory-allocator #memory #allocator #memory-map #stupid #interactive

nightly stupidalloc

一个将内存分配映射到文件的愚蠢内存分配器

3个不稳定版本

0.2.1 2023年12月29日
0.2.0 2023年12月29日
0.1.0 2023年7月7日

#337 in 内存管理

每月 23 次下载

MIT/Apache

43KB
604 代码行

Stupid alloc - 如果内存分配很烦人会怎样

主要是一个关于如何使内存分配器变得糟糕的奇怪练习。

此分配器将通过内存映射创建和打开文件以用作分配的数据。如果你启用interactive功能,它甚至会在程序分配每次东西时提示你输入文件名!酷!

如何使用它

不要

不过,真的要怎么用这个

使用 cargo add

cargo add stupidalloc

Cargo.toml 中手动指定依赖

[dependencies]
stupidalloc = { version = "0.2.1" }

interactive功能

此包附带一个功能,interactive,它将打开确认和文件选择对话框,而不是静默打开和分配内存。请自行承担风险,因为有时对话框不可用。此包使用native-dialog来实现此功能。

图形界面

graphics功能创建图形窗口,将内存内容显示为黑白像素,代表分配的位!点击每个像素可以设置位(左键点击)或清除位(右键点击)。你可以这样轻松修改内存内容!

此外,always-graphics功能将使每个新分配的图形窗口都启用,而不仅仅是用户按需创建。

图形窗口使用minifb包创建。

https://github.com/shadyfennec/stupidalloc/assets/68575248/b19790c7-bc9e-4a59-99c9-18d7e308739e

日志记录

logging包创建日志文件,以Markdown格式记录有关每个分配的有用信息。这对于调试很有用!

使用分配器

  • 您可以用它作为程序的全球分配器,但它可能导致程序运行不正常,比如在执行 main() 之前就提示分配内存!
use stupidalloc::StupidAlloc;

#[global_allocator]
static GLOBAL: StupidAlloc = StupidAlloc;

fn main() {
    // ...
}
  • 通过使用 allocator_api 夜间功能,您可以使用此分配器选择性地分配单个对象
// Requires nightly
#![feature(allocator_api)]

use stupidalloc::StupidAlloc;

fn main() {
    let normal_box = Box::new(1);

    let stupid_box = Box::new_in(1, StupidAlloc);
}

一种有趣的用法是在通过您喜欢的 stdin 读取来停止程序的执行后,然后使用十六进制编辑器查看分配文件(我可以推荐 Hexyl 吗?)

为此,分配器公开了一些辅助函数

  • StupidAlloc.state() 返回一个 HashMap,其中的键是内存映射的地址(因此是分配对象的地址),值是关联文件的 PathBuf
  • StupidAlloc 实现了 fmt::Display,因此运行 println!("{StupidAlloc}") 将打印当前正在跟踪的所有分配的漂亮摘要。
  • StupidAlloc.file_of(x) 将返回关联对象的文件,如果存在。显然,这仅适用于使用愚蠢分配器分配的内容。用法示例
// Still requires nightly
#![feature(allocator_api)]

use stupidalloc::StupidAlloc;

fn main() {
    let stupid_box = Box::new_in(1, StupidAlloc);

    // Since it's a Box<i32>, we need to pass &i32 to the function to get the 
    // address of where the integer is.
    let file = StupidAlloc.file_of(&*stupid_box).unwrap();

    // Go nuts with it!
}

另一个有趣的用法是能够查看数据在内存中的布局,而无需使用内存查看器或复杂的 GDB 语法!

例如,您是否想看看 Vec<T> 在内存中的组织方式?

use stupidalloc::StupidAlloc;

#[global_allocator]
static GLOBAL: StupidAlloc = StupidAlloc;

fn main() {
    let boxed_vec = Box::new(vec![1, 2, 3]);

    println!("{}", StupidAlloc.file_of(&*boxed_vec).unwrap().display());

    // Somehow pause execution
}

此程序将打印 Vec<T> 结构的分配文件路径(而不是 Vec 的分配,因为那样我们只会看到数字 1, 2, 3!)在十六进制查看器中打开它,您可以尝试猜测每个字段是什么,并将其与 结构定义 进行对照。如果您的系统允许您这样做(我知道 Windows 有点限制),请尝试修改长度和/或容量字段,并查看之后会发生什么!

免责声明

  • 我并不声称这个库是完美的,没有任何错误。这里可能有打字错误和错误,以及我没有测试且不工作的示例。如果有什么问题,请提交问题!
  • 如果您没有文件选择器/文件对话框功能(最小 i3 安装、纯 TTY 等),interactivity 将不会工作。
  • 同样,如果您完全没有图形环境,graphicsalways-graphics 也不会工作。
  • 我只在 Windows 和 Linux 上进行了测试。如果它在 MacOS 或其他操作系统上不工作,对不起。如果它在 Windows 或 Linux 上不工作:奇怪!联系我。
  • 如果您以任何方式修改内存文件,您将会破坏程序的内存,但鉴于这与操作 /proc/mem 在拓扑上是相同的,我将其视为一个酷特性。
  • 我可能还会稍微修改一下这个(稍微多一点点),以添加一些生活质量的特性,但这就是全部。这是一个垃圾邮件,不是一个严肃的库。

(旧) 示例

https://github.com/shadyfennec/stupidalloc/assets/68575248/f2490dc1-8412-4450-9359-7387f79682ea

依赖项

~2–13MB
~141K SLoC