使用`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可能使用其他分配器.最好的方法是公开一个带c_char
指针的Rust函数,为该指针构造一个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.
一种解决方法是将 entire CString
传递(指向)Python,并提供访问器函数以从中获取char指针.您只需将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屋!