Reputation: 969
I have a function with input of type ptr::NonNull<c_void>
. Usually this input is provided by C code. Legitimate input is of type: &(int){5}
.
However, I need to create some inputs in Rust. So I did the following:
let i = 5;
let data = &i as *const u32;
ptr::NonNull::new_unchecked(data as *mut _)
In case of legit input from C code, the following block executes:
ptr::NonNull::new_unchecked(x.data as *mut _)
where x.data
comes from a struct, where x
is of type X
:
#[repr(C)]
pub struct X {
data: *const c_void,
}
For reference, the code together looks something like:
if x.data.is_null() {
let i = 5;
let data = &i as *const u32;
ptr::NonNull::new_unchecked(data as *mut _)
} else {
// x.data is specified in C code through FFI as &(int){5}
ptr::NonNull::new_unchecked(x.data as *mut _)
}
However, when I attempt to dereference the value at a later stage, for the else
branch, I get 5
as expected. But for the if
branch, I get a large garbage value. I'm assuming it has to do with how I'm creating the raw pointer in Rust.
Upvotes: 1
Views: 4939
Reputation: 123
In your if
branch you are creating a locally scoped variable i
, getting a pointer (reference) to it and passing that reference to new_unchecked
which doesn't copy your data, it just encapsulates the pointer that you then pass outside of your scope.
Later in the program you try to access the data which is no longer in scope and thus you get unspecified data.
Try defining the data in a Box
and use into_raw()
to get your pointer
EDIT: Actually, something like this may be better:
let val = if x.data.is_null() {
5
} else {
*x.data
};
let data = &val as *const u32;
ptr::NonNull::new_unchecked(data as *mut _)
which takes the allocation out of the enclosing block.
Upvotes: 4