如何防止Rust程序释放(释放)它不拥有的C字节

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何防止Rust程序释放(释放)它不拥有的C字节相关的知识,希望对你有一定的参考价值。

libc有一个函数,该函数返回不应为free()d的字符串。可以从/etc/passwd读取用户的当前目录,但不应将其为free()d。如果我从指针创建字符串,程序将异常终止

free(): invalid pointer
Aborted (core dumped)

显然该代码不安全。

let pw = libc::getpwnam(username.as_ptr() as *const i8);
let cd = (*pw).pw_dir;
let len = libc::strlen(cd);
builder.current_dir(String::from_raw_parts(cd as *mut u8, len, len));

我可以mem::forget(s)字符串,但是会泄漏内存,至少必须将长度存储在某个位置。我只需要防止释放基础原始字节。项目是一台服务器,所以我不能忽略泄漏。

答案

String::from_raw_parts是在此处使用的错误功能。该函数只能用先前从String::from_raw_parts或同等方法获得的指针来调用,这显然在您的代码中不是这种情况,因为该字符串来自C库,甚至没有动态分配。

相反,应该使用String::into_raw_parts&str或为此目的设计的slice::from_raw_parts类型创建指向数据的slice::from_raw_parts。拥有str::from_utf8后,应将其复制到一个拥有的字符串中,然后使用该字符串调用str::from_utf8。用CStr调用CStr会编译,但是不安全,需要您证明该函数(及其调用的函数)从不调用&str

这里是一个例子:

builder.current_dir()

请注意,此代码实际上也不安全,因为它不能在多个线程中使用。您应该改用builder.current_dir(),或者更好的是,使用像&str那样的板条箱代替getpwnam

以上是关于如何防止Rust程序释放(释放)它不拥有的C字节的主要内容,如果未能解决你的问题,请参考以下文章

boost interprocess file_lock 无法锁定它不拥有的文件

在 C 或 C++ 中释放内存 [重复]

在函数中定义数组:float fltNum[10],该数组在内存中是如何被分配内存空间?何时被释放内存空间?c语言中

c语言是在声明变量的同时,分配内存的吗?程序结束运行了,内存会释放吗?

C 和 C++:释放已分配指针的一部分

2022-10-29:go语言中的defer能非常方便地处理资源释放问题,rust语言里如何实现defer功能呢?