Why does calling Vec :: resize before calling Vec :: set_len cause Vec to have data?
I have a problem that I don't understand:
fn cipher_with(key: &[u8], data: &[u8]) -> Vec<u8> {
let data_len = 16;
let mut data = data.to_vec();
data.resize(data_len, 2);
let mut output = Vec::<u8>::with_capacity(data_len);
unsafe { output.set_len(data_len) }
output
}
fn main() {
let key = "blabla".as_bytes();
let data = "lorem ipsum.".as_bytes();
println!("{:?}", cipher_with(&key, &data));
}
Prints:
[108, 111, 114, 101, 109, 32, 105, 112, 115, 117, 109, 46, 0, 0, 0, 0]
But how is it done? I have never given this meaning output
.
source to share
To add some detail to Peter's answer , check out this annotated version:
fn cipher_with(key: &[u8], data: &[u8]) -> Vec<u8> {
let data_len = 16;
let mut data = data.to_vec();
println!("{:?}", data.as_ptr());
data.resize(data_len, 2);
println!("{:?}", data.as_ptr());
let mut output = Vec::<u8>::with_capacity(data_len);
println!("{:?}", output.as_ptr());
unsafe { output.set_len(data_len) }
output
}
0x7fa6dba27000 0x7fa6dba1e0c0 0x7fa6dba27000
When the first vector is created, it has a length of 12. When it is resized to 16, a new selection will be created and the data copied. This is probably due to the implementation of the allocator, which normally allocates chunks. 16 would be a reasonable bucket size.
When the second vector is created, the allocator passes the same pointer as the first vector. Since nothing else has changed this memory during this time, it still contains any data in the data
.
source to share
You are using unsafe Rust, which can give you unpredictable results.
In this particular case, you are expanding the size Vec
into uninitialized memory. The values ββalready exist.
So let's take a look at some of the code:
let mut data = data.to_vec();
This copies the "lorem ipsum" data. on the heap as a vector.
data.resize(data_len, 2); // data_len = 16
This increases the capacity Vec
from 12 to 16 elements, which in this case are bytes. But in fact, based on what we can see, it looks like the implementation (or perhaps the optimizer) has decided that it is better to simply discard the first allocated memory range and copy the data into new memory.
let mut output = Vec::<u8>::with_capacity(data_len);
unsafe { output.set_len(data_len) }
This creates a new vector and doesn't give it a length. But you haven't initialized it, so the data will be as it was before.
It looks like it data.resize()
actually copied the value instead of just dropping the end of the vector. When it output
was allocated, it was allocated the same block of memory that was previously used, so it contains "lorem ipsum."
.
source to share