该文档mem::uninitialized
指出了使用该函数危险/不安全的原因:调用drop
未初始化的内存是未定义的行为.
因此,我相信这段代码应该是未定义的:
let a: TypeWithDrop = unsafe { mem::uninitialized() };
panic!("=== Testing ==="); // Destructor of `a` will be run (U.B)
Run Code Online (Sandbox Code Playgroud)
但是,我编写了这段代码,它在安全的Rust中运行,并且似乎没有受到未定义的行为的影响:
#![feature(conservative_impl_trait)]
trait T {
fn disp(&mut self);
}
struct A;
impl T for A {
fn disp(&mut self) { println!("=== A ==="); }
}
impl Drop for A {
fn drop(&mut self) { println!("Dropping A"); }
}
struct B;
impl T for B {
fn disp(&mut self) { println!("=== B ==="); }
}
impl …
Run Code Online (Sandbox Code Playgroud) std::lock()
在Rust中是否有像C++ 这样的工具来防止像这样的代码中的死锁:
type Type0 = Arc<Mutex<u8>>;
type Type1 = Arc<Mutex<u16>>;
fn foo(a: Type0, b: Type1) {
let a_guard = a.lock().unwrap();
let b_guard = b.lock().unwrap();
}
fn bar(a: Type0, b: Type1) {
let b_guard = b.lock().unwrap();
let a_guard = a.lock().unwrap();
}
Run Code Online (Sandbox Code Playgroud)
如果foo
由thread-0和bar
thread-1 调用,则可能出现死锁.有什么东西,希望变量,因为我可以有超过2,帮助我这个或我自己验证锁定顺序的正确性?
锁定给定
Lockable
对象lock1
,lock2
,...
,lockn
使用死锁避免算法,以避免死锁.
在C++中(如果错误请纠正我),通过常量引用的临时绑定应该比它绑定的表达式更长.我认为在Rust中也是如此,但在两种不同情况下我得到了两种不同的行为.
考虑:
struct A;
impl Drop for A { fn drop(&mut self) { println!("Drop A.") } }
struct B(*const A);
impl Drop for B { fn drop(&mut self) { println!("Drop B.") } }
fn main() {
let _ = B(&A as *const A); // B is destroyed after this expression itself.
}
Run Code Online (Sandbox Code Playgroud)
输出是:
Drop B.
Drop A.
Run Code Online (Sandbox Code Playgroud)
这是你所期望的.但现在如果你这样做:
fn main() {
let _b = B(&A as *const A); // _b will be dropped when scope exits main()
}
Run Code Online (Sandbox Code Playgroud)
输出是:
Drop …
Run Code Online (Sandbox Code Playgroud) 在某些情况下,我想利用Rust中的任何替代方法来解决C++的friend
关键字.在箱子A中我有以下模块:
mod a0:
pub struct A {
pub a0: u8,
a1: SomeType,
}
impl A {
pub fn fa0(...) { ... }
fn fa1(...) { ... }
}
Run Code Online (Sandbox Code Playgroud)
模块b0
并c0
需要访问所有公共和私人成员A
.代码不能这样做,除非它在mod a0
.我只想暴露A
,A::a0
并A::fa0
与其他与此箱子接口的箱子,但在这个箱子里我想要访问A
(公共和私人)的完整实现.
我通常最终做的事情如下:
mod a0:
pub struct A {
pub a0: u8,
inner: Inner
}
pub struct Inner { /* all pub fields */ }
pub fn get_inner<'a>(obj: &'a mut …
Run Code Online (Sandbox Code Playgroud) 我有crate-0,src/lib.rs
如下:
#[cfg(test)]
pub mod test_utils {
pub struct OnlyInTests(pub usize);
pub fn helper() -> usize { 999 }
#[test]
fn test_0() { let _ = OnlyInTests(helper()); }
}
Run Code Online (Sandbox Code Playgroud)
我也有crate-1,我需要在crate-0中定义的测试框架:
extern crate crate_0;
#[cfg(test)]
pub mod test_utils {
// This will error out - cannot find mod test_utils in crate_0
use crate_0::test_utils::{OnlyInTests, helper()};
#[test]
fn test_1() { let _ = OnlyInTests(helper()); }
}
Run Code Online (Sandbox Code Playgroud)
这里的代码很简单,可以复制粘贴,但实际上我有复杂的测试工具,我想在测试crate-1时使用它.
我无法将测试实用程序分离到不同的包中,因为我会得到循环依赖性错误:test_utils
将依赖于crate-0
创建内容并crate-0
依赖于test_utils
测试).我也不想这样做,因为还有更多的板条箱,其测试实用程序我想在依赖板条箱中使用.
以前当代码库是在C++中时,我有C++包装器文件,它将链接到代码库,我将运行swig
(支持C++ 11的版本3)来生成目标语言的接口文件(Python,JavaScript, C#等).然后当然将所有这些文件和库编译成一个共享对象,并从所需的语言中调用它.现在代码库被改为生锈.因此,对于swig工作,我有以下内容:
no_mangle
和extern
语法FFI
并编译成staticlib.现在我swig
在C文件上使用,获取目标语言的接口文件,将所有文件(第二步和第三步)和SWIG接口文件组合成一个共享对象,并从目标语言调用.
所以:
方法好吗?
我可以获得免费的功能.但是我对如何使成员函数(方法)工作感到困惑.在C++中,成员函数的第一个参数是隐式this
指针.所以我可以void*
将类或结构的句柄返回给C接口,将其传递给想要存储它的其他人(例如Firefox的jsctypes),然后再将reinterpret_cast
它接收到具体/实际类型并调用成员函数在上面.我怎么用Rust做到这一点?
例如,为
pub struct A { id: SomeType, }
impl A {
pub fn some_funct_0(&mut self) {}
pub fn some_funct_1(&self) {}
}
impl SomeTrait for A {
fn some_trait_funct(&mut self) {}
}
Run Code Online (Sandbox Code Playgroud)
那么如何A
从目标语言(Python,C等)甚至简单的C接口访问这些成员函数(应该是非托管的,在堆上我猜?)?
我正在尝试使用rustc_serialize将JSON反序列化为Rust结构.问题是某些JSON具有一些可选字段,即可能存在也可能不存在.遇到第一个缺席字段的那一刻,解码器似乎纾困并且不考虑后续字段,即使它们存在.有办法克服这个问题吗?
这是代码:
extern crate rustc_serialize;
#[derive(Debug)]
struct B {
some_field_0: Option<u64>,
some_field_1: Option<String>,
}
impl rustc_serialize::Decodable for B {
fn decode<D: rustc_serialize::Decoder>(d: &mut D) -> Result<Self, D::Error> {
Ok(B {
some_field_0: d.read_struct_field("some_field_0", 0, |d| rustc_serialize::Decodable::decode(d)).ok(),
some_field_1: d.read_struct_field("some_field_1", 0, |d| rustc_serialize::Decodable::decode(d)).ok(),
})
}
}
fn main() {
{
println!("--------------------------------\n1st run - all field present\n--------------------------------");
let json_str = "{\"some_field_0\": 1234, \"some_field_1\": \"There\"}".to_string();
let obj_b: B = rustc_serialize::json::decode(&json_str).unwrap();
println!("\nJSON: {}\nDecoded: {:?}", json_str, obj_b);
}
{
println!("\n\n--------------------------------\n2nd run - \"some_field_1\" absent\n---------------------------------");
let json_str = …
Run Code Online (Sandbox Code Playgroud) 1)此处发送的API返回Result<usize>
.这是为什么 ?在我看来,UDP发送是全部或全部.返回值似乎表明发送可以成功,但可能不会写入整个数据,这使得我的代码如下:
let mut bytes_written = 0;
while bytes_written < data.len() {
bytes_written += match udp_socket.send_to(&data[bytes_written..]) {
Ok(bytes_tx) => bytes_tx,
Err(_) => break,
}
}
Run Code Online (Sandbox Code Playgroud)
最近有人告诉我这完全没必要.但我不明白.如果这是真的,为什么回报Result<()>
不是,这也是我所期待的?
2)
对于读操作,虽然我明白了.我可以给它一个大小为100字节的缓冲区,但数据报可能只有50个字节长.所以基本上我应该只利用read_buf[..size_read]
.这里我的问题是如果缓冲区大小为100但数据报大小为150字节会发生什么?将recv_from
只填写100个字节并返回Ok(100, some_peer_addr)
?如果我重读,它会填写剩下的数据报吗?如果在我第二次读取之前另一个50字节的数据报到达怎么办?我是第二次得到剩余的50个字节,第三次得到50个字节的新数据报还是第二次得到100个字节,还包含新的数据报?或者将是一个错误,我将丢失我的初始读取的第一个数据报,永远无法恢复它?
let arr0 = [0u8; 15];
let arr1 = [0u8; arr0.len()]; // this fails
Run Code Online (Sandbox Code Playgroud)
我认为编译器应该能够将arr0的长度确定为编译时常量,不是吗?仍然将此标记为错误,表示找到变量而不是常量整数.
版:
rustc 1.0.0-nightly (ecf8c64e1 2015-03-21) (built 2015-03-22)
Run Code Online (Sandbox Code Playgroud) 我在用一些琐碎的代码排列时就注意到了这一点:
struct Base0 {};
struct Base1 {};
template<typename... Ts>
struct Derived: Ts... {};
int main() {
Derived<Base0, Base1> d0 {Base0{}, Base1{}}; // OK
Derived<Base0, Base1> d1 (Base0{}, Base1{}); // ERROR
}
Run Code Online (Sandbox Code Playgroud)
我认为两者d0
并d1
应导致编译错误,因为我看不出Derived
没有任何匹配的构造函数需要构造函数参数如通过和标志d0
的编译细。
我可能想念一些明显的东西。使它通过的统一初始化是什么?是聚合初始化还是什么?临时人员传给ctor的情况如何?
编辑
根据要求,我提供了喷出的副本粘贴:
main.cpp: In function ‘int main()’:
main.cpp:9:47: error: no matching function for call to ‘Derived::Derived(Base0, Base1)’
Derived<Base0, Base1> d1 (Base0{}, Base1{}); // ERROR
^
main.cpp:5:8: note: candidate: constexpr Derived::Derived()
struct Derived: Ts... {};
^~~~~~~
main.cpp:5:8: …
Run Code Online (Sandbox Code Playgroud) rust ×9
c++ ×1
c++17 ×1
destructor ×1
json ×1
mutex ×1
networking ×1
swig ×1
udp ×1
unit-testing ×1