Warm tip: This article is reproduced from stackoverflow.com, please click
rust

Rust pointer being freed was not allocated error

发布于 2020-04-05 23:37:01

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);
    }
}
Questioner
McGrady
Viewed
95
Matthieu M. 2020-02-01 00:36

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:

  • The memory at 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:

  • Ensure that nothing else uses the pointer after calling this function.

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.