Here's the situation, I want to do some data conversion from a string, and for convenience, I converted it to a pointer in the middle, and now I want to return the part of the string, but I'm stuck with this exception:
foo(74363,0x10fd2fdc0) malloc: *** error for object 0x7ff65ff000d1: pointer being freed was not allocated
foo(74363,0x10fd2fdc0) malloc: *** set a breakpoint in malloc_error_break to debug
When I try to debug the program, I got the error message as shown above. Here's my sample code:
fn main() {
unsafe {
let mut s = String::from_utf8_unchecked(vec![97, 98]);
let p = s.as_ptr();
let k = p.add(1);
String::from_raw_parts(k as *mut u8, 1, 1);
}
}
You should never use an unsafe
function without understanding its documentation, 100%.
So, what does String::from_raw_parts
says:
Safety
This is highly unsafe, due to the number of invariants that aren't checked:
- The memory at
ptr
needs to have been previously allocated by the same allocator the standard library uses, with a required alignment of exactly 1.length
needs to be less than or equal to capacity.capacity
needs to be the correct value.Violating these may cause problems like corrupting the allocator's internal data structures.
The ownership of ptr is effectively transferred to the String which may then deallocate, reallocate or change the contents of memory pointed to by the pointer at will. Ensure that nothing else uses the pointer after calling this function.
There are two things that stand out here:
ptr
needs to have been previously allocated.capacity
needs to be the correct value.And those are related to how allocations work in Rust. Essentially, deallocation only expects the very pointer value (and type) that allocation returned.
Shenanigans such as trying to deallocate a pointer pointing in the middle of an allocation, with a different alignment, or with a different size, are Not Allowed.
Furthermore, you also missed:
Here, the original instance of String
is still owning the allocation, and you are trying to deallocate one byte out of it. It cannot ever go well.
The example code starts to go wrong even before this, where
String::from_utf8_unchecked(vec![127, 128])
creates an invalidString
.@trentcl: Good catch, I was concentrating on the memory issues, but there are others as well.
@trentcl Sorry, I forgot that, my mistake.