fix leak; fix corruption

master
Avril 5 years ago
parent 3a7bb22d06
commit 82d6626226
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -2,8 +2,6 @@ use super::*;
use std::{ use std::{
mem::{ mem::{
replace,
MaybeUninit,
forget, forget,
}, },
}; };
@ -14,19 +12,21 @@ use ptr::{
pub struct IntoIter<T> pub struct IntoIter<T>
{ {
start: *mut T, start: *mut T,
current: *mut T, current_offset: usize,
sz: usize, sz: usize,
} }
impl<T> IntoIter<T> impl<T> IntoIter<T>
{ {
fn current_offset(&self) -> usize fn current(&mut self) -> *mut T
{ {
(self.current as usize) - (self.start as usize) unsafe {
self.start.offset(self.current_offset as isize)
}
} }
fn free_if_needed(&mut self) fn free_if_needed(&mut self)
{ {
if self.start != ptr::null() && self.current_offset() >= self.sz { if self.start != ptr::null() && self.current_offset >= self.sz {
unsafe { unsafe {
alloc::free(self.start as VoidPointer); alloc::free(self.start as VoidPointer);
} }
@ -40,12 +40,13 @@ impl<T> Iterator for IntoIter<T>
type Item = T; type Item = T;
fn next(&mut self) -> Option<Self::Item> fn next(&mut self) -> Option<Self::Item>
{ {
let output = if self.current_offset() >= self.sz { let output = if self.current_offset >= self.sz || self.sz == 0 {
None None
} else { } else {
unsafe { unsafe {
let output = replace(&mut (*self.current), MaybeUninit::zeroed().assume_init()); let output = crate::ptr::take(self.current());//replace(&mut (*self.current), MaybeUninit::zeroed().assume_init());
self.current = self.current.offset(1); self.current_offset+=1;
Some(output) Some(output)
} }
}; };
@ -71,7 +72,7 @@ impl<T> IntoIterator for HeapArray<T>
{ {
let output = Self::IntoIter { let output = Self::IntoIter {
start: self.ptr, start: self.ptr,
current: self.ptr, current_offset: 0,
sz: self.len(), sz: self.len(),
}; };
forget(self); forget(self);

@ -23,6 +23,8 @@ mod tests {
assert_eq!(heap.as_slice(), ["test one", "test two"]); assert_eq!(heap.as_slice(), ["test one", "test two"]);
} }
struct Unit;
#[test] #[test]
fn zero_size() { fn zero_size() {
let heap: HeapArray<u8> = heap![]; let heap: HeapArray<u8> = heap![];
@ -30,6 +32,14 @@ mod tests {
assert_eq!(&heap.as_slice(), &[]); assert_eq!(&heap.as_slice(), &[]);
assert_eq!(&heap_zst.as_slice(), &[(),(),()]); assert_eq!(&heap_zst.as_slice(), &[(),(),()]);
let heap = heap![Unit; 32];
let mut i=0;
for _x in heap.into_iter()
{
i+=1;
}
assert_eq!(i, 32);
} }
#[test] #[test]
@ -43,10 +53,10 @@ mod tests {
assert_eq!(x % 2, 1); assert_eq!(x % 2, 1);
} }
let non = heap!["string one".to_owned(), "string two".to_owned()]; let non = heap!["string one".to_owned(), "string two!".to_owned(), "string".to_owned()];
let iter = non.into_iter(); let iter = non.into_iter();
assert_eq!(iter.len(), 2); assert_eq!(iter.len(), 3);
for x in iter for x in iter
{ {
assert_eq!(&x[..6], "string"); assert_eq!(&x[..6], "string");
@ -318,6 +328,26 @@ impl<T> HeapArray<T>
op op
} }
pub fn free(self)
{
if self.ptr != ptr::null() {
unsafe {
alloc::free(self.ptr as VoidPointer);
}
}
std::mem::forget(self);
}
pub fn into_slice(self, slice: &mut [T])
{
let ptr = &mut slice[0] as *mut T;
assert!(slice.len() >= self.len());
unsafe{
ptr::memmove(ptr as ptr::VoidPointer, self.ptr as ptr::VoidPointer, self.len_bytes());
}
self.free();
}
pub fn from_boxed_slice(bx: Box<[T]>) -> Self pub fn from_boxed_slice(bx: Box<[T]>) -> Self
{ {
#[cfg(feature="assume_libc")] #[cfg(feature="assume_libc")]
@ -326,7 +356,7 @@ impl<T> HeapArray<T>
Self::from_raw_parts(Box::<[T]>::into_raw(bx) as *mut T, len) Self::from_raw_parts(Box::<[T]>::into_raw(bx) as *mut T, len)
} }
#[cfg(not(feature="assume_libc"))] #[cfg(not(feature="assume_libc"))]
{ //TODO: wtf? {
let len = bx.len(); let len = bx.len();
let out = Self::from(Vec::from(bx)); let out = Self::from(Vec::from(bx));
assert_eq!(len, out.len()); assert_eq!(len, out.len());
@ -445,10 +475,11 @@ impl<T> From<HeapArray<T>> for Vec<T>
fn from(ha: HeapArray<T>) -> Self fn from(ha: HeapArray<T>) -> Self
{ {
let mut output = Vec::with_capacity(ha.len()); let mut output = Vec::with_capacity(ha.len());
for item in ha.into_iter() unsafe {
{ ptr::memmove(output.as_mut_ptr() as ptr::VoidPointer, ha.ptr as ptr::VoidPointer, ha.len_bytes());
output.push(item); output.set_len(ha.len());
} }
ha.free();
output output
} }
} }

@ -33,3 +33,12 @@ pub unsafe fn take<T>(ptr: *mut T) -> T
{ {
mem::replace(&mut *ptr, MaybeUninit::zeroed().assume_init()) mem::replace(&mut *ptr, MaybeUninit::zeroed().assume_init())
} }
pub unsafe fn memcpy(dst: VoidPointer, src: ConstVoidPointer, size: usize) -> VoidPointer
{
libc::memcpy(dst as *mut c_void, src as *const c_void, size as size_t) as VoidPointer
}
pub unsafe fn memmove(dst: VoidPointer, src: ConstVoidPointer, size: usize) -> VoidPointer
{
libc::memmove(dst as *mut c_void, src as *const c_void, size as size_t) as VoidPointer
}

Loading…
Cancel
Save