What's causing this double free segfault?

I have an ArrayIterator that implements Iterator over some Object type defined as

pub struct ArrayIterator {
    start: *const Object,
    end: *const Object,
}

I first tried implementing Drop for it like so:

impl Drop for ArrayIterator {
    fn drop(&mut self) {
        let remaining = unsafe { self.end.offset_from(self.start) } as usize;
        let _ = unsafe {
            Vec::from_raw_parts(
                self.start as *mut Object,
                remaining,
                remaining,
            )
        };
    }
}

which seems to cause a segfault when dropping an ArrayIterator whose start and end differ. Not really sure why that's the case, I thought creating a Vec would reclaim the heap memory and when that goes out of scope the Drop impl of Vec is run, which frees the memory.

Changing the above to this fixes it:

impl Drop for ArrayIterator {
    fn drop(&mut self) {
        while self.start != self.end {
            unsafe {
                ptr::drop_in_place(self.start as *mut Object);
                self.start = self.start.offset(1);
            }
        }
    }
}

How do you make an ArrayIterator? If you didn't create it by calling into_raw_parts (or equivalent) on a Vec, you cannot drop it by using Vec::from_raw_parts.

Ah I see, I'm not creating it by calling into_raw_parts

impl IntoIterator for Array {
    type IntoIter = ArrayIterator;
    type Item = <ArrayIterator as Iterator>::Item;

    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        // Wrap `self` in `ManuallyDrop` to avoid running destructor.
        let arr = ManuallyDrop::new(self);
        let start = arr.items.as_ptr();
        let end = unsafe { start.add(arr.len()) };

        ArrayIterator { start, end }
    }
}

where arr.items is a ptr::NonNull<Object>.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.