I know from the docs of std::slice::from_raw_parts()
that ...
data
must be non-null and aligned even for zero-length slices. One reason for this is that enum layout optimizations may rely on references (including slices of any length) being aligned and non-null to distinguish them from other data. You can obtain a pointer that is usable as data for zero-length slices usingNonNull::dangling()
.
Based on that advice, I have done something like this in a function that's part of the C API of some of my Rust code (where data
is a pointer coming from a call to the C++ function std::vector::data()
in my case):
let data = len != 0 {
data
} else {
std::ptr::NonNull::dangling().as_ptr()
};
let my_slice = std::slice::from_raw_parts(data, len);
This seems cumbersome, but much worse, I have just realized that I'm using std::slice::from_raw_parts()
in other parts of my FFI code and there I did not do the dangling dance, which makes those already unsafe
functions even more unsafe.
A few days ago, I stumbled upon a different piece of advice (Reddit - Dive into anything):
The better way to turn C++ spans into Rust slices is
ptr::slice_from_raw_parts(ptr, len).as_ref()
, which producesOption<&[T]>
This seems very reasonable to me, and I guess it would change my example above into something like this:
let my_slice = std::ptr::slice_from_raw_parts(data, len).as_ref().unwrap_or(&[]);
Now (finally!) my questions:
Is this indeed the recommendation in this general situation?
Or is there an even better way to do this?
Shouldn't the documentation of std::slice::from_raw_parts()
point to std::ptr::slice_from_raw_parts()
(which it currently doesn't), mentioning this important use case?
And latter should probably mention this use case as well (if it is indeed recommended)?
And maybe there could even be a Clippy lint that warns about using std::slice::from_raw_parts()
with a potential NULL pointer?
But I guess this might lead to many false positives ...