I'm very new to rust and have run into this situation. The program listed below, crashes due to:
"free(): double free detected in tcache 2". I've tried this reading from primitives inside the
struct and that does not cause the issue.
Any ideas?
/**
* We want to store the data obtained from a disk file. The file consists
* of a bunch of bytes whose structure is defined in an external spec.
* This struct is a small example of what's in that spec. The spec does
* not include any padding between the tag and a_vec.
*/
#[repr(packed)]
struct S{
tag : u8,
a_vec : Vec<u8>
}
/**
* in this example we build the input from an array but in the real
* program, it would come from a disk file.
*
*/
fn main() {
let a_array : [u8;11] = [0x5, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A];
let a_vec = a_array.to_vec();
process(&a_vec);
}
/**
* After loading up a byte vector (e.g. from a disk file) here we want
* to have our way with it. In particular, we want to put it into a struct
* along with it's first byte value, its length, and the first word of it.
*
* @v : a vector containing the bytes we want to process
*/
fn process(v : &Vec<u8>){
let my_s = S{
tag : v[0], // the first byte is a tag
a_vec : get_bytes(&v, 1, v.len()-1) // the next bunch of bytes is data
};
// this works because the first byte is aligned
println!("tag = {:x?}",my_s.tag);
// but the vector is not so we have to fetch it using
// read_unaligned.
// This println fails due to "reference to packed field is unaligned"
// println!("doing something with a_vec {:x?}", my_s.a_vec);
// so we try this instead. But when the program ends we get:
//
// free(): double free detected in tcache 2
//
let unaligned = std::ptr::addr_of!(my_s.a_vec);
let v = unsafe { std::ptr::read_unaligned(unaligned)};
println!("doing something with a_vec {:x?}", v);
}
/**
* Get a subset of a vector of bytes and return it as a vector of bytes
*
* @buf : is a vector containing a bunch of bytes which could have come from a file
* @start_index : first byte of the subset
* @length : how many bytes to get from start_index
*/
fn get_bytes (buff : &Vec<u8>, start_index : usize, length : usize) -> Vec<u8>{
let mut rtn : Vec<u8> = Vec::new();
let mut
i : usize = 0;
while i < length {
rtn.push(buff[start_index+i]);
i += 1;
}
rtn
}
Output:
tag = 5
doing something with a_vec [31, 32, 33, 34, 35, 36, 37, 38, 39, 3a]
Errors:
Compiling playground v0.0.1 (/playground)
Finished dev [unoptimized + debuginfo] target(s) in 5.32s
Running `target/debug/playground`
free(): double free detected in tcache 2
timeout: the monitored command dumped core
/playground/tools/entrypoint.sh: line 11: 8 Aborted timeout --signal=KILL ${timeout} "$@"