这篇文章主要讨论了在 Rust 中使用 FFI 时内存释放的问题,以及defer机制的相关情况。
- 设置阶段:展示了一个简单的 Rust API,用于分配和返回动态分配的数组指针和长度,生成对应的 C 头文件后可以在 C 中使用。但代码存在一个微妙的错误,后续会继续探讨。
- 首次尝试正确释放内存:在 Rust 测试中尝试像 C 一样使用
libc的free函数来释放内存,测试通过但在 Miri 中会报错,因为 Rust 分配内存时调用的是libc的malloc,而释放内存需要libc的free,这导致了一些困惑,文档中对于直接free`Vec`指针的说法也存在矛盾。 - 第二次尝试正确释放内存:尝试通过假装内存是由
Box分配来解决问题,代码可以构建和测试通过,但在 Miri 中会报错,说明 Rust 在编译时和运行时看似正常,但在某些实验性分析器下会出现问题。 - 第三次尝试正确释放内存:在代码库中定义了一个新的
OwningArrayC结构体,用于携带Vec的容量信息,以正确释放内存,并添加了相应的函数。在 Rust 测试中使用该结构体后,Miri 不再报错。 Defer机制:使用scopeguardcrate 的defer!宏来自动释放内存,但在测试中会出现编译错误,因为defer块持有独占的可变引用,其他代码无法使用该引用。可能的解决方案:
- 在语言中添加
defer语句,并让 borrow checker 知道这个结构。 - 小心手动释放内存,但难以扩展。
- 使用类似
goto的方法,但代码可读性差。 - 通过重构代码使用句柄(数值 ID)来绕过 borrow checker。
- 改进 borrow checker 而不添加
defer。 - 使用 arena 来避免这些问题。
- 在语言中添加
- 结论:Rust + FFI 存在很多摩擦和问题,需要记住很多知识,容易出错,目前对于
defer机制还在讨论中。同时还提到了一个关于Vec指针可能为 null 的问题,在 C 调用时需要进行防御性检查。
总的来说,在 Rust 中使用 FFI 进行内存管理比较复杂,需要注意很多细节,defer机制的实现也存在一些困难。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用。你还可以使用@来通知其他用户。