gpt4 book ai didi

c - Rust C 互操作段错误(斜线 STATUS_ACCESS_VIOLATION)

转载 作者:行者123 更新时间:2023-12-03 11:43:47 33 4
gpt4 key购买 nike

在本地出现 2 个错误(两种情况下的代码几乎相同):

PS C:\Users\jonat\Projects\latex_classifier> cargo test --release
Finished release [optimized] target(s) in 0.07s
Running unittests (target\release\deps\latex_classifier-4191f26efde0cf48.exe)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

Running tests\tests.rs (target\release\deps\tests-aaa96da54d1827ef.exe)

running 1 test
error: test failed, to rerun pass '--test tests'

Caused by:
process didn't exit successfully: `C:\Users\jonat\Projects\latex_classifier\target\release\deps\tests-aaa96da54d1827ef.exe` (exit code: 0xc0000005, STATUS_ACCESS_VIOLATION)
PS C:\Users\jonat\Projects\latex_classifier>
在操场上:
   Compiling playground v0.0.1 (/playground)
Finished release [optimized] target(s) in 2.09s
Running `target/release/playground`
timeout: the monitored command dumped core
/playground/tools/entrypoint.sh: line 11: 7 Segmentation fault timeout --signal=KILL ${timeout} "$@"
为了在 Python 中调用一些 Rust 函数,我使用了 C 接口(interface) CFFI ,这似乎需要很多指针:

The ctype is usually some constant string describing the C type. It must be a pointer or array type.


而且我需要返回一个相对复杂的结构: CArray<CArray<SymbolPixels>>我发现 Python 在尝试某些访问时崩溃了,所以我在 Rust 中对其进行了测试,这导致了这些错误。
游乐场链接: https://play.rust-lang.org/?version=nightly&mode=release&edition=2018&gist=5609cf66ff7ee1104e978ce4545f9679
操场代码:
#![feature(vec_into_raw_parts)]

#![allow(unused)]
fn main() {
let segment = test_function();
unsafe {
println!("segment: {:.?}",segment);
let lines = std::slice::from_raw_parts(segment.ptr, segment.size);
println!("lines: {:.?}",lines);
for line in lines.iter() {
let symbols = std::slice::from_raw_parts(line.ptr, line.size);
for s in symbols.iter() {
println!("{:.?}",*s.bound);
// THE PROBLEM:
// The below line doesn't work
println!("{:.?}",*(*s.bound).min);
}
}
}
}

#[no_mangle]
pub extern "C" fn test_function() -> CArray<CArray<SymbolPixels>> {
// Just some test data
let temp: Vec<Vec<(Vec<u8>, Bound<usize>)>> = vec![
vec![(vec![1,2,3,4,5,6,7],Bound::new())],
vec![(vec![1,2,3,4,5,6,7],Bound::new()),(vec![1,2,3,4,5,6,7],Bound::new()),(vec![1,2,3,4,5,6,7],Bound::new())]
];
CArray::new(temp.into_iter().map(|sl| {
CArray::new(sl.into_iter().map(|(s, b)| SymbolPixels {
pixels: &CArray::new(s),
bound: &ReturnBound::new(b)
}).collect::<Vec<SymbolPixels>>())
}).collect::<Vec<CArray<SymbolPixels>>>())
}


#[derive(Clone, Debug)]
pub struct Bound<T: Ord + Copy> {
pub min: Point<T>,
pub max: Point<T>,
}
// This impl is just for easy testing here
impl Bound<usize> {
fn new() -> Bound<usize> {
Bound { min: Point { x:1, y:2 }, max: Point { x:5, y:9 } }
}
}

#[repr(C)]
#[derive(Debug)]
pub struct CArray<T> {
pub ptr: *const T,
pub size: usize,
}
impl<T> CArray<T> {
pub fn new(v: Vec<T>) -> Self {
let (ptr,size,_) = v.into_raw_parts();
CArray {
ptr: ptr,
size: size,
}
}
}

#[repr(C)]
#[derive(Debug)]
pub struct SymbolPixels {
pub pixels: *const CArray<u8>,
pub bound: *const ReturnBound
}

#[repr(C)]
#[derive(Debug)]
pub struct ReturnBound {
pub min: *const Point<u32>,
pub max: *const Point<u32>,
}
impl ReturnBound {
pub fn new(b: Bound<usize>) -> Self {
ReturnBound {
min: &Point { x: b.min.x as u32, y: b.min.y as u32 },
max: &Point { x: b.max.x as u32, y: b.max.y as u32 }
}
}
}

#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct Point<T: Ord> {
pub x: T,
pub y: T,
}
我不确定在这里提供什么其他信息,所以如果我遗漏了什么,请发表评论。
非常感谢有关此主题的任何帮助。

最佳答案

当我使用“cargo run”运行代码时,我得到了输出:

segment: CArray { ptr: 0x55ab1e3fac80, size: 2 }
lines: [CArray { ptr: 0x55ab1e3facd0, size: 1 }, CArray { ptr: 0x55ab1e3fad20, size: 3 }]
ReturnBound { min: 0x8, max: 0x55ab1d4a554e }
Segmentation fault
其中 ReturnBound.min 应该是一个指针,但 0x8 不是一个有效的指针。注释指出的 println 试图取消引用这个无效指针,这导致了段错误。
看起来没有分配后备内存,因此您存储在数据结构中的指针指向在您访问它之前已释放的内存。在处理原始指针时这是一种危险,因为它们未经检查,并且您不会收到编译器错误
例如,在:
pub fn new(b: Bound<usize>) -> Self {
ReturnBound {
min: &Point { x: b.min.x as u32, y: b.min.y as u32 },
max: &Point { x: b.max.x as u32, y: b.max.y as u32 }
}
} <-- the data behind the two Point structs will be dropped here
Point 在堆栈上分配,对该数据的引用存储在 ReturnBound 的最小值和最大值中。然后返回 ReturnBound,但分配给 Point 结构的数据将在 new() 函数的末尾被丢弃,然后该内存将被其他事物使用。您存储在 CArray 结构中的 Vec 数据也是如此。为了解决这个问题,您可以使用 libc::malloc (因为这是与 C 的接口(interface)),或者您可以使用 Box::leak() 或其他一些技巧来防止分配的内存被丢弃。
您也可以对其进行重构以避免需要指针,但这取决于您所连接的具体内容

关于c - Rust C 互操作段错误(斜线 STATUS_ACCESS_VIOLATION),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66586616/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com