mirror of
https://github.com/azalea-rs/simdnbt.git
synced 2025-08-02 15:36:03 +00:00
fix memory leak on error
This commit is contained in:
parent
4aa3effbf1
commit
33366ff085
4 changed files with 43 additions and 13 deletions
|
@ -50,10 +50,11 @@ fn bench_file(filename: &str, c: &mut Criterion) {
|
||||||
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
|
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
|
||||||
|
|
||||||
fn bench(c: &mut Criterion) {
|
fn bench(c: &mut Criterion) {
|
||||||
// bench_file("bigtest.nbt", c);
|
bench_file("bigtest.nbt", c);
|
||||||
// bench_file("simple_player.dat", c);
|
bench_file("simple_player.dat", c);
|
||||||
bench_file("complex_player.dat", c);
|
bench_file("complex_player.dat", c);
|
||||||
// bench_file("level.dat", c);
|
bench_file("level.dat", c);
|
||||||
|
|
||||||
// bench_file("stringtest.nbt", c);
|
// bench_file("stringtest.nbt", c);
|
||||||
// bench_file("inttest16.nbt", c);
|
// bench_file("inttest16.nbt", c);
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ impl<'a> NbtCompound<'a> {
|
||||||
return Err(Error::MaxDepthExceeded);
|
return Err(Error::MaxDepthExceeded);
|
||||||
}
|
}
|
||||||
|
|
||||||
let alloc_mut = unsafe { alloc.get().as_mut().unwrap() };
|
let alloc_mut = unsafe { alloc.get().as_mut().unwrap_unchecked() };
|
||||||
|
|
||||||
let mut tags = alloc_mut.start_named_tags(depth);
|
let mut tags = alloc_mut.start_named_tags(depth);
|
||||||
loop {
|
loop {
|
||||||
|
@ -43,14 +43,26 @@ impl<'a> NbtCompound<'a> {
|
||||||
if tag_type == END_ID {
|
if tag_type == END_ID {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let tag_name = read_string(data)?;
|
|
||||||
|
|
||||||
tags.push((
|
let tag_name = match read_string(data) {
|
||||||
tag_name,
|
Ok(name) => name,
|
||||||
NbtTag::read_with_type(data, alloc, tag_type, depth)?,
|
Err(_) => {
|
||||||
));
|
alloc_mut.finish_named_tags(tags, depth);
|
||||||
|
// the only error read_string can return is UnexpectedEof, so this makes it
|
||||||
|
// slightly faster
|
||||||
|
return Err(Error::UnexpectedEof);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let tag = match NbtTag::read_with_type(data, alloc, tag_type, depth) {
|
||||||
|
Ok(tag) => tag,
|
||||||
|
Err(e) => {
|
||||||
|
alloc_mut.finish_named_tags(tags, depth);
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
tags.push((tag_name, tag));
|
||||||
}
|
}
|
||||||
let alloc_mut = unsafe { alloc.get().as_mut().unwrap() };
|
let alloc_mut = unsafe { alloc.get().as_mut().unwrap_unchecked() };
|
||||||
let values = alloc_mut.finish_named_tags(tags, depth);
|
let values = alloc_mut.finish_named_tags(tags, depth);
|
||||||
|
|
||||||
Ok(Self { values })
|
Ok(Self { values })
|
||||||
|
|
|
@ -80,7 +80,14 @@ impl<'a> NbtList<'a> {
|
||||||
let alloc_mut = unsafe { alloc.get().as_mut().unwrap() };
|
let alloc_mut = unsafe { alloc.get().as_mut().unwrap() };
|
||||||
let mut tags = alloc_mut.start_unnamed_list_tags(depth);
|
let mut tags = alloc_mut.start_unnamed_list_tags(depth);
|
||||||
for _ in 0..length {
|
for _ in 0..length {
|
||||||
tags.push(NbtList::read(data, alloc, depth + 1)?)
|
let tag = match NbtList::read(data, alloc, depth + 1) {
|
||||||
|
Ok(tag) => tag,
|
||||||
|
Err(e) => {
|
||||||
|
alloc_mut.finish_unnamed_list_tags(tags, depth);
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
tags.push(tag)
|
||||||
}
|
}
|
||||||
let alloc_mut = unsafe { alloc.get().as_mut().unwrap() };
|
let alloc_mut = unsafe { alloc.get().as_mut().unwrap() };
|
||||||
alloc_mut.finish_unnamed_list_tags(tags, depth)
|
alloc_mut.finish_unnamed_list_tags(tags, depth)
|
||||||
|
@ -92,7 +99,14 @@ impl<'a> NbtList<'a> {
|
||||||
let alloc_mut = unsafe { alloc.get().as_mut().unwrap() };
|
let alloc_mut = unsafe { alloc.get().as_mut().unwrap() };
|
||||||
let mut tags = alloc_mut.start_unnamed_compound_tags(depth);
|
let mut tags = alloc_mut.start_unnamed_compound_tags(depth);
|
||||||
for _ in 0..length {
|
for _ in 0..length {
|
||||||
tags.push(NbtCompound::read_with_depth(data, alloc, depth + 1)?)
|
let tag = match NbtCompound::read_with_depth(data, alloc, depth + 1) {
|
||||||
|
Ok(tag) => tag,
|
||||||
|
Err(e) => {
|
||||||
|
alloc_mut.finish_unnamed_compound_tags(tags, depth);
|
||||||
|
return Err(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
tags.push(tag);
|
||||||
}
|
}
|
||||||
let alloc_mut = unsafe { alloc.get().as_mut().unwrap() };
|
let alloc_mut = unsafe { alloc.get().as_mut().unwrap() };
|
||||||
alloc_mut.finish_unnamed_compound_tags(tags, depth)
|
alloc_mut.finish_unnamed_compound_tags(tags, depth)
|
||||||
|
|
|
@ -261,6 +261,7 @@ pub struct ContiguousTagsAllocator<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> ContiguousTagsAllocator<T> {
|
impl<T> ContiguousTagsAllocator<T> {
|
||||||
|
#[inline(never)]
|
||||||
fn grow(&mut self) {
|
fn grow(&mut self) {
|
||||||
let new_cap = if self.is_new_allocation {
|
let new_cap = if self.is_new_allocation {
|
||||||
// this makes sure we don't allocate 0 bytes
|
// this makes sure we don't allocate 0 bytes
|
||||||
|
@ -297,6 +298,7 @@ impl<T> ContiguousTagsAllocator<T> {
|
||||||
self.alloc.len = self.size;
|
self.alloc.len = self.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub fn push(&mut self, value: T) {
|
pub fn push(&mut self, value: T) {
|
||||||
// check if we need to reallocate
|
// check if we need to reallocate
|
||||||
if self.alloc.len == self.alloc.cap {
|
if self.alloc.len == self.alloc.cap {
|
||||||
|
@ -305,7 +307,8 @@ impl<T> ContiguousTagsAllocator<T> {
|
||||||
|
|
||||||
// push the new tag
|
// push the new tag
|
||||||
unsafe {
|
unsafe {
|
||||||
std::ptr::write(self.alloc.ptr.as_ptr().add(self.alloc.len), value);
|
let end = self.alloc.ptr.as_ptr().add(self.alloc.len);
|
||||||
|
std::ptr::write(end, value);
|
||||||
}
|
}
|
||||||
self.alloc.len += 1;
|
self.alloc.len += 1;
|
||||||
self.size += 1;
|
self.size += 1;
|
||||||
|
|
Loading…
Add table
Reference in a new issue