为什么java Atomics使用sun Unsafe类而不是使用synchronize block/volatile?
考虑以下代码:
public unsafe struct MyStruct
{
public fixed int Nums[128];
}
private static void DoSomething()
{
MyStruct s = new MyStruct();
unsafe
{
int val = s.Nums[23];
Console.WriteLine(val.ToString()); //Is this guaranteed to be "0"?
}
}
Run Code Online (Sandbox Code Playgroud)
这样的话,是不是保证新建一个的时候MyStruct,at每个索引的值都Nums为0呢?
在我自己的测试中,它似乎确实被初始化为默认值,但我问是因为它是unsafe.
我有一个结构,我想在多个线程之间作为不可变引用共享。我正在使用“Arc”来做到这一点,但为了让 Arc 工作,我必须为我的结构实现发送和同步特征。问题就在这里,Rust Book 中写到“手动实现发送和同步是不安全的”。
解决这个问题的办法是什么?
是否有其他方法可以在多个线程之间共享不可变引用?
我有一个Test我想实现的结构体std::future::Future,它会轮询function:
use std::{
future::Future,
pin::Pin,
task::{Context, Poll},
};
struct Test;
impl Test {
async fn function(&mut self) {}
}
impl Future for Test {
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
match self.function() {
Poll::Pending => Poll::Pending,
Poll::Ready(_) => Poll::Ready(()),
}
}
}
Run Code Online (Sandbox Code Playgroud)
那没有用:
error[E0308]: mismatched types
--> src/lib.rs:17:13
|
10 | async fn function(&mut self) {}
| - the `Output` of this `async fn`'s expected opaque …Run Code Online (Sandbox Code Playgroud) 我正在用MaybeUninitRust 和 FFI做一些似乎有效的事情,但我怀疑可能不健全/依赖于未定义的行为。
我的目标是让一个 structMoreA扩展一个 struct A,包括A作为初始字段。然后调用一些写入 struct 的 C 代码A。然后MoreA根据A.
在我的应用程序中, 的附加字段MoreA都是整数,因此我不必担心分配给它们的(未初始化的)先前值。
这是一个最小的例子:
use core::fmt::Debug;
use std::mem::MaybeUninit;
#[derive(Clone, Copy, PartialEq, Debug)]
#[repr(C)]
struct A(i32, i32);
#[derive(Clone, Copy, PartialEq, Debug)]
#[repr(C)]
struct MoreA {
head: A,
more: i32,
}
unsafe fn mock_ffi(p: *mut A) {
// write doesn't drop previous (uninitialized) occupant of p
p.write(A(1, 2));
}
fn main() {
let mut b = MaybeUninit::<MoreA>::uninit(); …Run Code Online (Sandbox Code Playgroud) 正如 Rust 参考文档所说
\n\n\n\n\n违反指针别名规则。&mut T 和 &T 遵循 LLVM\xe2\x80\x99s 作用域 noalias 模型,除非 &T 包含 UnsafeCell。
\n
实在是太暧昧了。
\n我想知道 Rust 中 noalias 的未定义行为发生在什么时刻&mut。
是下面的任何一个,还是其他什么?
\n\n\n\n\n\n
\n- 当定义两个
\n&mut指向同一地址时?- 当两个
\n&mut指向同一地址的对象暴露于锈迹时?- \n
&mut当对指向任何其他地址的同一地址执行任何操作时&mut?
例如,这段代码显然是 UB 的:
\n\nunsafe {\n let mut x = 123usize;\n let a = (&mut x as *mut usize).as_mut().unwrap(); // created, but not accessed\n let b = (&mut x as *mut …Run Code Online (Sandbox Code Playgroud) 我有一个固定大小[T; SIZE]的 T 类型值数组,它是有序的(它实现了Ord,但不一定是Clone或Default)。我想提取数组的最小值并删除所有其他值。
在 nightly rust 中,我可以使用它array::IntoIter来实现这一点,但如果可能的话,我希望我的代码能够在稳定版上编译。
目前,我正在使用以下(操场):
// Don't call this function if T has a custom Drop implementation or invalid bit patterns
unsafe fn get_min<T: Ord>(mut arr: [T; SIZE]) -> T {
let (idx, _) = arr.iter().enumerate().min_by(|(_, x), (_, y)| x.cmp(y)).unwrap();
unsafe { replace(&mut arr[idx], MaybeUninit::uninit().assume_init()) }
}
Run Code Online (Sandbox Code Playgroud)
当然,我对此不是很满意......有没有更安全,也许不那么冗长的解决方案?
我正在实现一个算法,为了保持所需的时间复杂度,我想在移动Vec时保存一个指向元素的指针。Vec
具体来说,是这样的:
fn main() {
let mut v: Vec<usize> = vec![1, 2, 3];
let ptr: *mut usize = &mut v[1] as *mut usize;
let mut u: Vec<usize> = v;
assert!(ptr == &mut u[1] as *mut usize);
println!("{}", unsafe { *ptr });
}
Run Code Online (Sandbox Code Playgroud)
实际的代码更复杂,涉及树状数据结构,其中每个顶点拥有一个Vec子节点。我在这里不是在问编码风格,但我的问题是是否可以依赖这段代码来完成我认为它所做的事情。
由于Vec必须将其内容保存在堆上,并且移动相当于memcpyRust,我认为可移动的事实Vec意味着我的代码是健全的(即不是未定义的行为)。它是否正确?
我有一个i32传递到我的键值数据库的。
let a = 1234i32;
db.put(&a.to_be_bytes());
Run Code Online (Sandbox Code Playgroud)
但我把它恢复为&[u8],如何将其转换回i32?
更新:这个例子几乎满足了我的要求。
use std::convert::TryInto;
fn read_be_i32(input: &[u8]) -> i32 {
i32::from_be_bytes(input.try_into().unwrap())
}
Run Code Online (Sandbox Code Playgroud) unsafe ×10
rust ×8
arrays ×1
async-await ×1
asynchronous ×1
atomic ×1
c# ×1
concurrency ×1
future ×1
immutability ×1
java ×1
llvm ×1
pointers ×1
raw-pointer ×1
struct ×1
vector ×1