1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 19:27:45 +00:00

AK: Use an OwnPtr for the VectorImpl.

I don't know why it wasn't implemented this way already. This fixes a leak
in operator=(Vector&&) that we were hitting on Ext2FS write.
This commit is contained in:
Andreas Kling 2019-03-17 15:53:03 +01:00
parent 4e451c1e92
commit ef05d8cbf6

View file

@ -11,13 +11,17 @@ template<typename T> class Vector;
template<typename T> template<typename T>
class VectorImpl { class VectorImpl {
public: public:
~VectorImpl() { } ~VectorImpl()
static VectorImpl* create(int capacity) {
for (int i = 0; i < m_size; ++i)
at(i).~T();
}
static OwnPtr<VectorImpl> create(int capacity)
{ {
int size = sizeof(VectorImpl) + sizeof(T) * capacity; int size = sizeof(VectorImpl) + sizeof(T) * capacity;
void* slot = kmalloc(size); void* slot = kmalloc(size);
new (slot) VectorImpl(capacity); new (slot) VectorImpl(capacity);
return (VectorImpl*)slot; return OwnPtr<VectorImpl>((VectorImpl*)slot);
} }
int size() const { return m_size; } int size() const { return m_size; }
@ -60,9 +64,8 @@ public:
~Vector() { clear(); } ~Vector() { clear(); }
Vector(Vector&& other) Vector(Vector&& other)
: m_impl(other.m_impl) : m_impl(move(other.m_impl))
{ {
other.m_impl = nullptr;
} }
Vector(const Vector& other) Vector(const Vector& other)
@ -74,19 +77,13 @@ public:
Vector& operator=(Vector&& other) Vector& operator=(Vector&& other)
{ {
if (this != &other) { if (this != &other)
m_impl = other.m_impl; m_impl = move(other.m_impl);
other.m_impl = nullptr;
}
return *this; return *this;
} }
void clear() void clear()
{ {
for (int i = 0; i < size(); ++i) {
at(i).~T();
}
kfree(m_impl);
m_impl = nullptr; m_impl = nullptr;
} }
@ -177,8 +174,7 @@ public:
void append(Vector<T>&& other) void append(Vector<T>&& other)
{ {
if (!m_impl) { if (!m_impl) {
m_impl = other.m_impl; m_impl = move(other.m_impl);
other.m_impl = nullptr;
return; return;
} }
Vector<T> tmp = move(other); Vector<T> tmp = move(other);
@ -217,6 +213,8 @@ public:
void append(const T* values, int count) void append(const T* values, int count)
{ {
if (!count)
return;
ensure_capacity(size() + count); ensure_capacity(size() + count);
for (int i = 0; i < count; ++i) for (int i = 0; i < count; ++i)
new (m_impl->slot(m_impl->m_size + i)) T(values[i]); new (m_impl->slot(m_impl->m_size + i)) T(values[i]);
@ -235,9 +233,8 @@ public:
new (new_impl->slot(i)) T(move(m_impl->at(i))); new (new_impl->slot(i)) T(move(m_impl->at(i)));
m_impl->at(i).~T(); m_impl->at(i).~T();
} }
kfree(m_impl);
} }
m_impl = new_impl; m_impl = move(new_impl);
} }
void resize(int new_size) void resize(int new_size)
@ -305,7 +302,7 @@ private:
return max(int(4), capacity + (capacity / 4) + 4); return max(int(4), capacity + (capacity / 4) + 4);
} }
VectorImpl<T>* m_impl { nullptr }; OwnPtr<VectorImpl<T>> m_impl;
}; };
} }