Hello, I know the code could be fully written without any unsafe code, but I am doing a research and learning how things work "under the hood".个
Back to the topic,我已经编写了一段不安全的 rust 代码,在我看来,它应该可以正常工作,没有任何问题.
定义是这样的:
pub struct Container {
inner: Pin<Box<String>>,
half_a: *const str,
half_b: *const str,
}
impl Container {
const SEPARATOR: char = '-';
pub fn new(input: impl AsRef<str>) -> Option<Self> {
let input = input.as_ref();
if input.is_empty() {
return None
}
// Making sure the value is never moved in the memory
let inner = Box::pin(input.to_string());
let separator_index = inner.find(Container::SEPARATOR)?;
let inner_ref = &**inner;
let half_a = &inner_ref[0..separator_index];
let half_b = &inner_ref[separator_index+1..];
// Check if the structure definition is met (populated values + only one separator)
if half_a.is_empty() || half_b.is_empty() || half_b.contains(Container::SEPARATOR) {
return None;
}
Some(Self {
half_a: half_a as *const str,
half_b: half_b as *const str,
inner,
})
}
pub fn get_half_a(&self) -> &str {
unsafe {
&*self.half_a
}
}
pub fn get_half_b(&self) -> &str {
unsafe {
&*self.half_b
}
}
}
总之,它接受任何可以表示为字符串引用的输入,在堆上创建输入的固定克隆,获取指向该值的两个半部分的地址,并将其作为 struct 返回.
现在,当我做测试时:
let valid = Container::new("first-second").unwrap();
assert_eq!(valid.get_half_a(), "first");
assert_eq!(valid.get_half_b(), "second");
它应该运行时不会出现任何panic ,事实上,这就是Windows上的情况.它多次编译并运行,没有任何问题,但当它在Ubuntu上运行时,我收到一个错误,显示地址不再指向内存中的有效位置:
thread 'tests::types::container' panicked at 'assertion failed: `(left == right)`
left: `"�K\u{13}϶"`,
right: `"first"`', research/src/tests/types.rs:77:5
这里的问题可能是什么?我错过了什么吗? I am running this code as GitHub action with the following flag 100.
以下是操场的URL,显示此代码运行时没有任何问题: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=d36b19de4d0fa05340191f5107029d75个
我预计在不同的操作系统上运行这段代码不会出现任何问题.