使用`as_ptr()`时如何停止内存泄漏?

Waf*_*nut 8 python ctypes memory-leaks ffi rust

因为这是我第一次学习系统编程,所以我很难绕过规则.现在,我对内存泄漏感到困惑.让我们考虑一个例子.比如说,Rust正在抛出Python将要捕获的指针(指向一个字符串).

在Rust中,(我只是发送指针CString)

use std::ffi::CString;

pub extern fn do_something() -> *const c_char {
    CString::new(some_string).unwrap().as_ptr()
}
Run Code Online (Sandbox Code Playgroud)

在Python中,(我正在取消引用指针)

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
Run Code Online (Sandbox Code Playgroud)

现在,我的问题是释放内存.我认为它应该在Python中释放,但随后所有权弹出.因为,as_ptr似乎采用了不可变的引用.所以,我对是否应该释放Rust或Python中的内存(或两者兼而有之)感到困惑.如果它会是Rust,那么当控制流重新回到Python时,我应该如何释放它呢?

小智 8

你的Rust函数do_something构造一个临时函数CString,将一个指针指向它,然后删除它CString.该*const c_char是你返回它的即时无效.如果你在夜间,你可能想要CString#into_ptr而不是CString#as_ptr,因为前者消耗了CString没有释放记忆的东西.在稳定的,你可以mem::forgetCString.然后你可以担心谁应该释放它.

从Python中解放将是棘手或不可能的,因为Rust可能使用不同的分配器.最好的方法是公开一个带有c_char指针的Rust函数,为该指针构造一个CString(而不是将数据复制到一个新的分配中),然后删除它.不幸的是,中间部分(创建CString)现在似乎不可能稳定:CString::from_ptr不稳定.

解决方法是将整个CString(指针)传递给Python并提供一个访问器函数来从中获取char指针.您只需将盒子CString打包并将盒子转换为原始指针即可.然后你可以有另一个函数将指针转换回一个框并让它掉落.