使用`as_ptr()`时如何阻止内存泄漏? [英] How to stop memory leaks when using `as_ptr()`?
问题描述
由于这是我第一次学习系统编程,我很难理解规则.现在,我对内存泄漏感到困惑.让我们考虑一个例子.比如说,Rust 正在抛出一个指针(指向一个字符串),Python 会捕捉到这个指针.
Since it's my first time learning systems programming, I'm having a hard time wrapping my head around the rules. Now, I got confused about memory leaks. Let's consider an example. Say, Rust is throwing a pointer (to a string) which Python is gonna catch.
在 Rust 中,(我只是发送 CString
的指针)
In Rust, (I'm just sending the pointer of the CString
)
use std::ffi::CString;
pub extern fn do_something() -> *const c_char {
CString::new(some_string).unwrap().as_ptr()
}
在 Python 中,(我正在取消引用指针)
In Python, (I'm dereferencing the pointer)
def call_rust():
lib = ctypes.cdll.LoadLibrary(rustLib)
lib.do_something.restype = ctypes.c_void_p
c_pointer = lib.do_something()
some_string = ctypes.c_char_p(c_pointer).value
现在,我的问题是关于释放内存.我认为它应该在 Python 中被释放,但随后所有权突然出现.因为,as_ptr
似乎采用了不可变的引用.因此,我对是否应该在 Rust 或 Python (或两者?) 中释放内存感到困惑.如果它是 Rust,那么当控制流返回到 Python 时我应该如何释放它?
Now, my question is about freeing the memory. I thought it should be freed in Python, but then ownership pops in. Because, as_ptr
seems to take an immutable reference. So, I got confused about whether I should free the memory in Rust or Python (or both?). If it's gonna be Rust, then how should I go about freeing it when the control flow has landed back into Python?
推荐答案
你的 Rust 函数 do_something
构造一个临时的 CString
,将一个指针放入其中,然后 删除CString
.*const c_char
从您返回它的那一刻起就无效.如果你在夜间,你可能想要 CString#into_ptr
而不是 CString#as_ptr
,因为前者消耗 CString
而不释放内存.在稳定版上,您可以mem::forget
CString
.然后你可以担心谁应该释放它.
Your Rust function do_something
constructs a temporary CString
, takes a pointer into it, and then drops the CString
. The *const c_char
is invalid from the instant you return it. If you're on nightly, you probably want CString#into_ptr
instead of CString#as_ptr
, as the former consumes the CString
without deallocating the memory. On stable, you can mem::forget
the CString
. Then you can worry about who is supposed to free it.
从 Python 中释放将是棘手或不可能的,因为 Rust 可能使用不同的分配器.最好的方法是公开一个 Rust 函数,它接受一个 c_char
指针,为该指针构造一个 CString
(而不是将数据复制到新的分配中),然后删除它.不幸的是,中间部分(创建 CString
)目前在稳定版上似乎是不可能的:CString::from_ptr
不稳定.
Freeing from Python will be tricky or impossible, since Rust may use a different allocator. The best approach would be to expose a Rust function that takes a c_char
pointer, constructs a CString
for that pointer (rather than copying the data into a new allocation), and drops it. Unfortunately the middle part (creating the CString
) seems impossible on stable for now: CString::from_ptr
is unstable.
一种解决方法是将(指向)整个CString
传递给 Python,并提供一个访问器函数来从中获取字符指针.您只需要将 CString
装箱并将该框转换为原始指针.然后你可以有另一个函数将指针转换回一个盒子并让它下降.
A workaround would to pass (a pointer to) the entire CString
to Python and provide an accessor function to get the char pointer from it. You simply need to box the CString
and transmute the box to a raw pointer. Then you can have another function that transmutes the pointer back to a box and lets it drop.
这篇关于使用`as_ptr()`时如何阻止内存泄漏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!