string - 使用 malloced 字符串创建 Rust 字符串是否安全?
问题描述
我正在使用一个返回malloc
ed 字符串的 C API:
char *foo(int arg);
我可以在不O(n)
复制的情况下在 Rust 代码中重用该内存吗?
let p: *mut libc::c_char = foo(42);
let len = strlen(p);
let s: String = String.from_raw_parts(p, len, len);
文件说
at 的内存
ptr
必须事先由标准库使用的同一分配器分配。
我找不到标准库使用的分配器。
解决方案
一般来说,从不是String
从 Rust 分配的字符串创建 a 是不安全的。
Rust 0.11.0到 1.31.1 使用了 jemalloc。Rust 1.32.0更改为使用系统的默认分配器。
此外,Rust 1.28.0引入了一种机制,应用程序可以使用该机制将全局分配器替换为他们选择的一个。
需要注意的是,尽管 Rust 现在默认使用系统的默认分配器,但这并不意味着 C 库使用相同的分配器,即使它是字面上的malloc
. 例如,在 Windows 上,如果您使用的是使用 Visual C++ 2008 编译的 C 库,而您的 Rust 二进制文件是使用 Visual Studio 2019 构建工具编译的,那么您的进程中将加载两个C 运行时库:C 库将使用msvcr90.dll而你的 Rust 二进制文件将使用ucrtbase.dll。每个 C 运行时库管理自己的堆,因此一个分配的内存不能被另一个释放。
一个设计良好的 C 库应该提供一个函数来为库可能分配给自己的每种类型的资源释放资源。返回指向此类分配的指针或句柄的函数应该记录应该调用哪个函数来释放资源。有关设计良好的 API 的示例,请参阅有关使用 LLVM 的 C API 的其他问题。
也许您实际上并不需要String
? CStr
如果可能,请考虑改用。ACStr
类似于 a str
,所以它只是一个内存视图,它不关心它是如何分配的,但它比str
. 您可以将 a 转换CStr
为str
using CStr::to_str
(CStr
必须包含 UTF-8 字符串才能成功转换)。
如果库中确实有释放字符串的函数,您可能还想编写一个包装器结构,该结构将自动处理解除分配并将 deref to CStr
. 这个结构将表示一个拥有的字符串,类似于String
or CString
,但内存由库管理,而不是 Rust 的全局分配器。例如:
extern crate libc; // 0.2.62
use std::ffi::CStr;
use std::ops::Deref;
extern {
fn libfoo_free(string: *mut libc::c_char);
}
struct LibfooString(*mut libc::c_char);
impl Drop for LibfooString {
fn drop(&mut self) {
unsafe {
libfoo_free(self.0);
}
}
}
impl Deref for LibfooString {
type Target = CStr;
fn deref(&self) -> &Self::Target {
unsafe {
CStr::from_ptr(self.0)
}
}
}
推荐阅读
- firebase - FlutterFirebaseMessagingBackgroundService 和 FlutterFirebaseMessagingPlugin 未解析
- canvas - 使用颜色、noiseDetail() 以及 xoff 和 yoff 递增的速率来实现不同的视觉效果
- machine-learning - 如何处理重复的文本数据但具有不同的标签或类?
- android - 如何使用 android 解析 RecyclerView 中的 json?
- .net - 查看加密的 Kafka 消息中的标头
- html - 使用@media 规则时,如何防止打印输出中出现不需要的分页符?
- reactjs - 反应安装同一组件之一(弹出窗口)
- python - 将python脚本导入powerBI并发布仪表板
- kotlin - 错误:计算数组总和时出现 IndexOutOfBoundsException
- c# - 如何从文本框中获取特定文本并传输到另一个文本框?