我正在尝试更多地了解Rust中的FFI以及与C库(特别是libc )的链接。 在我的“任务”中,我遇到了以下问题。
C中的正常模式
void(* sig_set(int sig, void(*handler)(int))) { // uninitialized sigaction structs struct sigaction new_action, old_action; // assign options to new action new_action.sa_flags = SA_RESTART; new_action.sa_handler = handler; sigemptyset(&new_action.sa_mask); if(sigaction(sig, &new_action, &old_action) < 0) { fprintf(stderr, "Error: %s!\n", "signal error"); exit(1); } return old_action.sa_handler; }在Rust中尝试
fn sig_init(sig: i32, handler: fn(i32)->()) -> usize { unsafe { let mut new_action: libc::sigaction; let mut old_action: libc::sigaction; new_action.sa_flags = 0x10000000; new_action.sa_sigaction = handler as usize; libc::sigemptyset(&mut new_action.sa_mask as *mut libc::sigset_t); libc::sigaction( sig, &mut new_action as *mut libc::sigaction, &mut old_action as *mut libc::sigaction ); old_action.sa_sigaction } }当我尝试上述操作时,编译器将抛出以下错误以使用可能未初始化的变量。
error: use of possibly uninitialized variable: `<variable here>` [E0381]这是有道理的,因为如果从sa_mask读取sa_mask可能会发生非常糟糕的事情。 所以我在上面的第3行尝试了以下内容。
let mut new_action: libc::sigaction = libc::sigaction{ sa_sigaction: handler as usize, sa_flags: 0x10000000, sa_mask: mask, };这不起作用,因为上面的例子中缺少_restorer ,但_restorer是私有的。 那么如何解决这个问题或一个相似的情况呢? 你会使用像mem::transmute这样的东西吗?
I'm trying to learn more about the FFI in Rust and linking with C libraries (specifically libc). While on my "quest" I came accross the following problem.
Normal pattern in C
void(* sig_set(int sig, void(*handler)(int))) { // uninitialized sigaction structs struct sigaction new_action, old_action; // assign options to new action new_action.sa_flags = SA_RESTART; new_action.sa_handler = handler; sigemptyset(&new_action.sa_mask); if(sigaction(sig, &new_action, &old_action) < 0) { fprintf(stderr, "Error: %s!\n", "signal error"); exit(1); } return old_action.sa_handler; }Attempt in Rust
fn sig_init(sig: i32, handler: fn(i32)->()) -> usize { unsafe { let mut new_action: libc::sigaction; let mut old_action: libc::sigaction; new_action.sa_flags = 0x10000000; new_action.sa_sigaction = handler as usize; libc::sigemptyset(&mut new_action.sa_mask as *mut libc::sigset_t); libc::sigaction( sig, &mut new_action as *mut libc::sigaction, &mut old_action as *mut libc::sigaction ); old_action.sa_sigaction } }When I tried the above the compiler will throw the following error for the use of a possibly uninitialized variable.
error: use of possibly uninitialized variable: `<variable here>` [E0381]This makes sense as very bad things could happen if sigemptyset were to read from sa_mask. So I tried the following on line 3 of the above.
let mut new_action: libc::sigaction = libc::sigaction{ sa_sigaction: handler as usize, sa_flags: 0x10000000, sa_mask: mask, };This will not work as _restorer is missing in the above example, but _restorer is private. So how would one get around this problem or a simmilar situation? Would you use something like mem::transmute?
最满意答案
标准库定义了几个处理初始化的函数。 它们是通用的,因此可用于初始化任何类型的值。
首先,有std::mem::uninitialized() ,它给你一个未初始化的值。 LLVM将认为内容未定义,并将基于此执行积极的优化。 您必须在读取之前初始化任何值。
其次,有std::mem::zeroed() ,它为你提供一个存储用零填充的值。 此功能unsafe因为这样的值对于所有类型都不一定合法。 zeroed()适用于“普通旧数据”(POD)类型。
The standard library defines a couple of functions to deal with initialization. They are generic, so they can be used to initialize values of any type.
First, there's std::mem::uninitialized(), which gives you an uninitialized value. LLVM will consider the contents to be undefined, and will perform aggressive optimizations based on this. You must initialize any value before it's read.
Second, there's std::mem::zeroed(), which gives you a value whose storage is filled with zeroes. This function is unsafe because such a value is not necessarily legal for all types. zeroed() is appropriate for "plain old data" (POD) types.
更多推荐
发布评论