Fix memory leak in List, Map and Set

This commit is contained in:
Daniel Chappuis 2018-04-04 18:37:24 +02:00
parent 0307a1d9be
commit fea3e44856
3 changed files with 51 additions and 12 deletions

15
src/containers/List.h Normal file → Executable file
View File

@ -32,6 +32,7 @@
#include <cassert>
#include <cstring>
#include <iterator>
#include <memory>
namespace reactphysics3d {
@ -204,8 +205,18 @@ class List {
if (mBuffer != nullptr) {
// Copy the elements to the new allocated memory location
std::memcpy(newMemory, mBuffer, mSize * sizeof(T));
if (mSize > 0) {
// Copy the elements to the new allocated memory location
T* destination = static_cast<T*>(newMemory);
T* items = static_cast<T*>(mBuffer);
std::uninitialized_copy(items, items + mSize, destination);
// Destruct the previous items
for (size_t i=0; i<mSize; i++) {
items[i].~T();
}
}
// Release the previously allocated memory
mAllocator.release(mBuffer, mCapacity * sizeof(T));

24
src/containers/Map.h Normal file → Executable file
View File

@ -68,10 +68,16 @@ class Map {
keyValue = nullptr;
}
/// Copy-constructor
Entry(const Entry& entry) {
hashCode = entry.hashCode;
next = entry.next;
keyValue = entry.keyValue;
}
/// Destructor
~Entry() {
assert(keyValue == nullptr);
}
};
@ -155,8 +161,16 @@ class Map {
newBuckets[i] = -1;
}
// Copy the old entries to the new allocated memory location
std::memcpy(newEntries, mEntries, mNbUsedEntries * sizeof(Entry));
if (mNbUsedEntries > 0) {
// Copy the old entries to the new allocated memory location
std::uninitialized_copy(mEntries, mEntries + mNbUsedEntries, newEntries);
// Destruct the old entries in the previous location
for (int i=0; i < mNbUsedEntries; i++) {
mEntries[i].~Entry();
}
}
// Construct the new entries
for (int i=mNbUsedEntries; i<newCapacity; i++) {
@ -391,7 +405,7 @@ class Map {
mEntries = static_cast<Entry*>(mAllocator.allocate(mCapacity * sizeof(Entry)));
// Copy the buckets
std::memcpy(mBuckets, map.mBuckets, mCapacity * sizeof(int));
std::uninitialized_copy(map.mBuckets, map.mBuckets + mCapacity, mBuckets);
// Copy the entries
for (int i=0; i < mCapacity; i++) {
@ -710,7 +724,7 @@ class Map {
mEntries = static_cast<Entry*>(mAllocator.allocate(mCapacity * sizeof(Entry)));
// Copy the buckets
std::memcpy(mBuckets, map.mBuckets, mCapacity * sizeof(int));
std::uninitialized_copy(map.mBuckets, map.mBuckets + mCapacity, mBuckets);
// Copy the entries
for (int i=0; i < mCapacity; i++) {

24
src/containers/Set.h Normal file → Executable file
View File

@ -67,10 +67,16 @@ class Set {
value = nullptr;
}
/// Copy-constructor
Entry(const Entry& entry) {
hashCode = entry.hashCode;
next = entry.next;
value = entry.value;
}
/// Destructor
~Entry() {
assert(value == nullptr);
}
};
@ -154,8 +160,16 @@ class Set {
newBuckets[i] = -1;
}
// Copy the old entries to the new allocated memory location
std::memcpy(newEntries, mEntries, mNbUsedEntries * sizeof(Entry));
if (mNbUsedEntries > 0) {
// Copy the old entries to the new allocated memory location
std::uninitialized_copy(mEntries, mEntries + mNbUsedEntries, newEntries);
// Destruct the old entries at previous location
for (int i=0; i<mNbUsedEntries; i++) {
mEntries[i].~Entry();
}
}
// Construct the new entries
for (int i=mNbUsedEntries; i<newCapacity; i++) {
@ -390,7 +404,7 @@ class Set {
mEntries = static_cast<Entry*>(mAllocator.allocate(mCapacity * sizeof(Entry)));
// Copy the buckets
std::memcpy(mBuckets, set.mBuckets, mCapacity * sizeof(int));
std::uninitialized_copy(set.mBuckets, set.mBuckets + mCapacity, mBuckets);
// Copy the entries
for (int i=0; i < mCapacity; i++) {
@ -651,7 +665,7 @@ class Set {
mEntries = static_cast<Entry*>(mAllocator.allocate(mCapacity * sizeof(Entry)));
// Copy the buckets
std::memcpy(mBuckets, set.mBuckets, mCapacity * sizeof(int));
std::uninitialized_copy(set.mBuckets, set.mBuckets + mCapacity, mBuckets);
// Copy the entries
for (int i=0; i < mCapacity; i++) {