Python 如何修复传递int数组时的分段错误?
我有一个Rust(1.2)库,我想使用Rust的FFI使用Python(3.4)中的函数。我在约塞米蒂的OSX 10.10上 几乎所有my函数都将可变切片引用作为输入:Python 如何修复传递int数组时的分段错误?,python,numpy,segmentation-fault,rust,ffi,Python,Numpy,Segmentation Fault,Rust,Ffi,我有一个Rust(1.2)库,我想使用Rust的FFI使用Python(3.4)中的函数。我在约塞米蒂的OSX 10.10上 几乎所有my函数都将可变切片引用作为输入: pub fn myfunction<T>(array: &mut [T]) { ... } 这很好:使用python的ctypes模块,我可以使用numpy数组调用ffi\u myfunction(): #!/usr/bin/env python3 import ctypes import numpy a
pub fn myfunction<T>(array: &mut [T]) { ... }
这很好:使用python的ctypes模块,我可以使用numpy数组调用ffi\u myfunction()
:
#!/usr/bin/env python3
import ctypes
import numpy as np
rustlib = ctypes.CDLL("target/debug/libmylib.dylib")
array = np.arange(5, dtype=np.int8)
rustlib.ffi_myfunction(ctypes.c_void_p(array.ctypes.data), len(array))
我还使用libc::int16_t
、libc::int32_t
和libc::int64_t
实现了rust,我可以用np.int16
、np.int32
和np.int64
调用它们
我还有第二组要从Python调用的Rust函数。这些函数略有不同,因为它们对向量(而不是切片)采用可变引用:
不幸的是,当从Python调用ffi\u myotherfunction()
时,我遇到了一个分段错误
经过一些调查,我可以说:
println!()
在myotherfunction()
或ffi\u myotherfunction()
中的任意位置执行宏,使函数正常运行。输出与预期一致myotherfunction()
,而是来自对Vec::from_raw\u parts()
的调用。例如,我可以从ffi\u myotherfunction()
注释掉对myotherfunction()的调用,只留下不安全的块,segfault仍然发生
slice::from_raw_parts_mut()
和Vec::from_raw_parts()
之间似乎存在差异
但我不明白是什么导致了这个错误。我错过什么了吗?我做错什么了吗?numpy存储数据的方式会有问题吗?或者可能是关于生命的东西,借来的东西,或者其他我不了解的概念
谢谢大家! 您只应使用
Vec::from_raw_parts
处理已在Rust code中通过Rust的分配器分配的数据。其他任何东西都是不安全的
我希望Python使用malloc,但Rust使用jemalloc。如果jemalloc被指示释放一个不是由jemalloc分配的地址,我相信它会崩溃。因此,如果一个向量被释放(即,它超出了作用域,它的析构函数被运行),或者如果它需要重新分配(例如,如果你把一个元素推到它上面),你会遇到崩溃
因此,第一个问题是
Vec
正在运行其析构函数;完成后,可以通过调用std::mem::forget(to_sort)
对其进行修改。另一个问题是,任何再分配都会崩溃,这是非常危险的;你已经基本上做到了,你不能安全地可变地访问你的向量,你必须非常小心地对待它。实际上,您应该假设Vec
上的所有内容都会崩溃。如果你想用它做什么,你应该用&mut[T]
。所以我应该用slice::from_raw_parts_mut()
而不是Vec::from_raw_parts()
,是吗?
#!/usr/bin/env python3
import ctypes
import numpy as np
rustlib = ctypes.CDLL("target/debug/libmylib.dylib")
array = np.arange(5, dtype=np.int8)
rustlib.ffi_myfunction(ctypes.c_void_p(array.ctypes.data), len(array))
pub fn myotherfunction<T>(array: &mut Vec<T>) { ... }
#[no_mangle]
pub extern "C" fn ffi_myotherfunction(array_pointer: *const libc::int8_t, n: libc::size_t) {
assert!(!array_pointer.is_null());
assert!(n != 0);
let mut to_sort = unsafe {
Vec::from_raw_parts(array_pointer as *mut i8, n as usize, n as usize)
};
myotherfunction(&mut to_sort);
}