-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Description
What it does
Often in FFI, some APIs will take *c_void
or *mut c_void
to indicate arbitrary objects from the caller side. When interacting with such APIs in Rust it is common to allocate something with {Box,Rc,Arc}::into_raw
and then casting the raw pointer. For deallocating you often get the c_void
pointer back from the FFI API and you would turn it into the corresponding owned/shared pointer with {Box,Rc,Arc}::from_raw
, after which you can drop it.
However, it is easy to run into the pitfall of calling from_raw
with the c_void
pointer. Note that the definition of, say, Box::from_raw
is:
pub unsafe fn from_raw(raw: *mut T) -> Box<T>
meaning that if you pass a *mut c_void
you will get a Box<c_void>
. Per the safety requirements in the documentation, for this to be safe, c_void
would need to have the same memory layout as the original type, which is often not the case. And even if it was the case, if the original type or one of its fields (or one of its fields, recursively) had a Drop
implementation, that implementation would not run when this newly recreated box is dropped. (And similarly for Rc
and Arc
.)
While it is possible to purposefully create a Box<c_void>
, it's hard to see any case where it would be useful. Therefore, uses of Box::from_raw::<c_void>
can be safely assumed to be a mistake, and clippy should have a lint for it.
Lint Name
from-raw-cvoid
Category
No response
Advantage
- Remove an easy pitfall of FFI, particularly with some C or C++ APIs.
Drawbacks
- Might conflict with genuine usages of
Box<c_void>
, but those are incredibly rare, and not good practice.
Example
use std::ffi::c_void;
let ptr = Box::into_raw(Box::new(42usize)) as *mut c_void;
// pass `ptr` through C FFI or something.
let _ = unsafe { Box::from_raw(ptr) };
Could be written as:
use std::ffi::c_void;
let ptr = Box::into_raw(Box::new(42usize)) as *mut c_void;
// pass `ptr` through C FFI or something.
let _ = unsafe { Box::from_raw(ptr as *mut usize) };