Related
There is a memory leak that I see in Valgrind in my C++ program. I'm wondering where I should place delete statements to remote it. Thank you.
#include <iostream>
using namespace std;
void showFloatArray(float f1[10]) {
for (int i=0; i < 10; i++)
cout << " " << f1[i];
cout << endl;
}
float *getFloatArrayOne() {
float *floatArray = new float[10];
for (int i=0; i < 10; i++)
floatArray[i] = (float) i;
return(floatArray);
}
float *getFloatArrayTwo() {
float myFloatArray[10];
float *floatArray = myFloatArray;
for (int i=0; i < 10; i++)
floatArray[i] = (float) i;
return(floatArray);
}
int main()
{
float *f1 = getFloatArrayOne();
float *f2 = getFloatArrayTwo();
showFloatArray(f1);
showFloatArray(f2);
}
Anytime you create a pointer with new then you have to make sure you call delete on that pointer before the program ends.
For example:
int main()
{
Object * obj = new Object;
return 0; //leaky program!
}
int main()
{
Object * obj = new Object;
delete obj;
return 0; //non-leaky program!
}
Quick re-write
Better to get caller to make allocations. Caller then knows to allocate and de-allocate. If your function (eg a library) allocates, then caller might be in doubt about whether objects must be de-allocated.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// remove fixed size restriction on function
void print_array(float* f, size_t size) {
for (size_t i=0; i < size; i++)
cout << " " << f[i];
cout << endl;
}
// pass in array
float* getFloatArrayOne(float f[], size_t size) {
for (size_t i=0; i < size; i++)
f[i] = (float)i;
return f;
}
// pass in ptr - caller responsible for allocation and de-allocating
float *getFloatArrayTwo(float* f, size_t size) {
for (size_t i=0; i < size; i++)
*(f+i) = (float)i; // dereference pointer + offset method
return f;
}
// You can use any algorithm you like to generate numbers
struct myincrementer {
myincrementer(float startval) : n_(startval) {}
float operator()() { return ++n_; } // change to n_++ to start printing first value
float n_;
};
int main()
{
const int size = 10;
float* floatArray = new float[size]();
float *f1 = getFloatArrayOne(floatArray, size);
float myFloatArray[size] = {0};
float *f2 = getFloatArrayTwo(myFloatArray, size);
print_array(f1, size);
print_array(f2, size);
delete [] floatArray; // note [] form
// More advanced approach
vector<float> vec;
myincrementer myi(0.0);
generate_n(back_inserter(vec), 10, myi);
std::copy(vec.begin(), vec.end(), std::ostream_iterator<float>(std::cout, " "));
}
'Modern' C++ typically avoids leaks by not using new and delete directly, instead delegating the management of resources like memory to objects that handle them internally.
However since this is homework it seems worthwhile to learn not just good practices which eliminate problems, but the technical details of what a leak is and the formal requirements to avoid a leak, independent of any particular method for effectively carrying out those requirements.
So here it is: A memory leak occurs when a pointer value is returned by a successful call to an allocation function and no subsequent call to the correct deallocation function is made using the value returned by the allocation function. That is, a leak occurs when you allocate memory and then fail to deallocate it.
Allocations by malloc() must be deallocated with free(). Allocations by new must be deallocated with delete. Allocations by new[] must be deallocated with delete[].
int *x = malloc(sizeof(int)); // C code
if (x) {
// allocation succeeded, you can use the resource and you should free() it
// ... use
free(x);
}
int *y = new int;
delete y;
int *z = new int[10];
delete [] z;
In Practice
So fixing or avoiding memory leaks requires 'merely' that your program call the deallocation function for every successful allocation. The challenge however, is that this is difficult to do in an arbitrary or ad-hoc manner. In order to avoid leaks in practice you need to establish patterns of allocation and deallocation that can be easily managed and verified.
So here are some pointers to get you started on learning about the practicalities of resource management:
The basic practice for managing resource across many languages is to define "ownership semantics" for specific resources. You define rules for determining what part of the program is responsible for any particular allocated resource, and rules for how responsibility for a particular resource may be handed off from one part of the program to another.
Typically ownership semantics are defined such that the part of a program that allocates a resource is responsible for it. That may seem obvious, but there are alternatives. E.g. a program could designate a single entity that takes responsibility for cleaning up everything, and then the rest of the program just allocates at will and has nothing to do with clean-up. But more commonly whatever allocates a resource takes responsibility for it.
For example a function that allocates some dynamic memory to perform its task also frees that memory when its done:
void foo(int n) {
int *arr = malloc(n * sizeof(int));
// ...
free(arr)
}
Another way to 'take responsibility' for an allocated resource is to be explicit about about requirements for resource management when resources are passed off. For example a function which needs to allocate memory and pass that memory back to the caller may specify "callers of foo() must call free_foo(foo_results) when the foo results are no longer needed."
foo_t *foo() {
foo_t *f = malloc(sizeof(foo_t));
// ...
return f;
}
void free_foo(foo_t *f) {
free(f);
}
Exceptions
For correct resource management whatever rules of ownership semantics have been designed must be followed in all circumstances. There's one language feature supported by C++ that has historically given some people trouble, making them think they'd correctly handled resource management responsibilities when in fact they hadn't. This feature is exceptions.
I won't go into details about exceptions, but it suffices to say that they are the reason that code such as:
doSomething();
cleanup();
is incorrect. And once you learn the idiomatic C++ way to manage resources it should be absolutely obvious that the above is wrong, without you even needing to know what doSomething() does. (One common criticism of exceptions is that they require you to know if doSomething() might throw an exception in order to know how to do the cleanup, which could require manually examining a huge amount of code. But since one can do the cleanup correctly without knowing if doSomething() throws, that criticism is incorrect.)
C++
In C++ a specific practice for managing resources has been developed, called RAII, for Resource Acquisition Is Initialization. It's reliable and easy to use, and correctly handles circumstances such as exceptions. Under RAII a resource is represented as an object, and the correct ownership semantics are encoded into the object's special functions: its destructor, copy/move constructors, and copy and move assignment operators.
Thus you acquire a resource by initializing an object of the right type and you access the resource through that object. If the resource can be copied or moved then you can copy or move the object. If the resource is fundamentally not copyable or moveable then the object is non-copyable or non-moveable, and trying to copy or move it will produce a compiler error.
Some resource managing, RAII types in the C++ standard library are:
std::array: a template class that manages a static, in-place memory buffer, presented as an array of objects
std::vector: a template class that manages dynamic memory, presented as a resizable array of objects.
std::string: a template class that manages static and/or dynamic memory, presented as a resizable array of char.
std::shared_ptr: a template class that implements reference counting ownership semantics. By default the resource is a dynamically allocated object, but this can be configured.
std::unique_ptr: a template class that implements unique ownership semantics. By default the resource is a dynamically allocated object or array, but this can be configured.
For more info on resource management in C++ you can visit http://exceptionsafecode.com/
You should probably just delete f1, as the main function terminates. The first one is allocated on the heap dynamically and it remains allocated though-out execution, and it needs to be deleted. As for the second one, you declare it statically (on the stack), and when the function getFloatArrayTwo() terminates, it deallocates already the vector, deleting it again my result a runtime double delete error. After showFloatArray(f2); you should put delete f1, and the leaks should dissapear.
Hope this to be of help.
I have an OOP entity-component system that currently works like this:
// In the component system
struct Component { virtual void update() = 0; }
struct Entity
{
bool alive{true};
vector<unique_ptr<Component>> components;
void update() { for(const auto& c : components) c->update(); }
}
// In the user application
struct MyComp : Component
{
void update() override { ... }
}
To create new entities and components, I use C++'s usual new and delete:
// In the component system
struct Manager
{
vector<unique_ptr<Entity>> entities;
Entity& createEntity()
{
auto result(new Entity);
entities.emplace_back(result);
return *result;
}
template<typename TComp, typename... TArgs>
TComp& createComponent(Entity& mEntity, TArgs... mArgs)
{
auto result(new TComp(forward<TArgs>(mArgs)...));
mEntity.components.emplace_back(result);
return result;
}
void removeDead() { /* remove all entities with 'alive == false' - 'delete' is called here by the 'unique_ptr' */ }
}
// In the user application
{
Manager m;
auto& myEntity(m.createEntity());
auto& myComp(m.createComponent<MyComp>(myEntity));
// Do stuff with myEntity and myComp
m.removeDead();
}
The system works fine, and I like the syntax and flexibility. However, when continuously adding and removing entities and components to the manager, memory allocation/deallocation slows down the application. (I've profiled and determined that the slow down is caused by new and delete).
I've recently read that it's possible to pre-allocate heap memory in C++ - how can that be applied to my situation?
Desired result:
// In the user application
{
Manager m{1000};
// This manager can hold about 1000 entities with components
// (may not be 1000 because of dynamic component size,
// since the user can define it's on components, but it's ok for me)
auto& myEntity(m.createEntity());
auto& myComp(m.createComponent<MyComp>(myEntity));
// Do stuff with myEntity and myComp
m.removeDead();
// No 'delete' is called here! Memory of the 'dead' entities can
// be reused for new entity creation
}
// Manager goes out of scope: 'delete' is called here
There are a few things you can do to make the implementation of your design scale better.
In your current implementation there are two memory allocations per Entity and Component. The first one allocates an object and the second one when the object is put into the vector. The second one happens when the vector runs out of space and allocates a bigger array and moves the old elements into the new array.
In this case the best you can do is to use intrusive lists. That is, each of Entity and Component become also list nodes. Then, after these have been allocated no extra memory allocations are necessary to put the object into a list. Use a single or double-linked list from Boost.Intrusive, or write your own. This is how Linux kernel keeps track of many different objects.
The next step is to preallocate Entity and Component elements. Preallocating could be something as simple as a global array of these, or something more sophisticated, such as Boost.Pool. There are quite a few ways to build a memory pool of objects.
Once Entity and Component are preallocated and intrusive lists are used you are done.
An example which uses boost components:
#include <boost/intrusive/list.hpp>
#include <boost/pool/pool_alloc.hpp>
#include <new>
namespace bi = boost::intrusive;
// api.h
//
// Object pooling support begin.
//
template<class T>
struct Pool
{
static boost::pool_allocator<T> pool;
};
// Singleton. Although it is defined in the header, the linkers
// make sure there is only one instance of it in the application.
// It is instantiated on demand when Pool<T> is used.
template<class T>
boost::pool_allocator<T> Pool<T>::pool;
template<class Derived>
struct Pooled // use it on the most derived class only, not on intermediate base classes
{
// Automatically use the object pool for plain new/delete.
static void* operator new(size_t) { return Pool<Derived>::pool.allocate(1); }
static void operator delete(void* p) { return Pool<Derived>::pool.deallocate(static_cast<Derived*>(p), 1); }
};
//
// Object pooling support end.
//
// Using bi::list_base_hook<bi::link_mode<bi::auto_unlink> > because it automatically
// unlinks from the list when the object is destroyed. No need to manually
// remove the object from the list when an object is about to be destroyed.
struct Component
: bi::list_base_hook<bi::link_mode<bi::auto_unlink> > // make it an intrusive list node
{
virtual void update() = 0;
virtual ~Component() {}
};
struct Entity
: bi::list_base_hook<bi::link_mode<bi::auto_unlink> > // make it an intrusive list node
, Pooled<Entity> // optional, make it allocated from the pool
{
bool active = false;
bi::list<Component, bi::constant_time_size<false> > components;
~Entity() {
for(auto i = components.begin(), j = components.end(); i != j;)
delete &*i++; // i++ to make sure i stays valid after the object is destroyed
}
void update() {
for(auto& c : components)
c.update();
}
};
struct Manager
{
bi::list<Entity, bi::constant_time_size<false> > entities;
~Manager() {
for(auto i = entities.begin(), j = entities.end(); i != j;)
delete &*i++; // i++ to make sure i stays valid after the object is destroyed
}
Entity& createEntity() {
auto result = new Entity;
entities.push_back(*result);
return *result;
}
template<typename TComp, typename... TArgs>
TComp& createComponent(Entity& mEntity, TArgs... mArgs)
{
auto result = new TComp(std::forward<TArgs>(mArgs)...);
mEntity.components.push_back(*result);
return *result;
}
void removeDead() {
for(auto i = entities.begin(), j = entities.end(); i != j;) {
auto& entity = *i++;
if(!entity.active)
delete &entity;
}
}
};
// user.cc
struct MyComp
: Component
, Pooled<MyComp> // optional, make it allocated from the pool
{
void update() override {}
};
int main() {
Manager m;
auto& myEntity(m.createEntity());
auto& myComp(m.createComponent<MyComp>(myEntity));
m.removeDead();
}
In the above example boost::pool_allocator<T> actually uses new to allocate objects and then it keeps reusing destroyed objects rather than invoking delete on them. You can do better by preallocating all objects, but there are many ways to do so depending on your requirements, so that I use boost::pool_allocator<T> for simplicity to avoid hair splitting here. You can change the implementation of Pooled<T> to something like Pooled<T, N> where N stands for the maximum number of objects, the rest of the code stays the same because it uses plain new/delete which happen to be overridden for objects allocated from a pool.
C++ supports class-specific memory pools for this kind of thing. The general-purpose new/delete pair inevitably trades off among
Time spent searching for a free block of the right size to meet each request
Time spent coalescing free blocks
Time spent maintaining and perhaps reorganizing internal data structures to make the above two operations faster.
The primary way to gain speed is to avoid these tradeoffs entirely with custom allocators that - as you say - pre-allocate a big chunk of memory viewed as a simple array of free objects all of the same size. Initially these are all linked on a free list, where the link pointers occupy the first bytes of each block "overlaid" where the data will eventually go. Allocation is just unchaining a block from the head of the free list - a "pop" operation needing about 2 instructions. Deallocation is a "push:" two more instructions. In many cases, memory hardware can be set to generate a trap when the the pool is empty so there is no per-allocation overhead for detecting
this error condition. (In GC systems the same trick is used to initiate collection with no overhead.)
In your case you'd need two pools: one for Entities and one for Components.
Defining your own pool allocator is not so hard, especially if your application is single threaded. See this document for a tutorial treatment.
Using most of answers and Google as references, I implemented some pre-allocation utilities in my SSVUtils library.
Prealloc.h
Example:
using MemUnit = char;
using MemUnitPtr = MemUnit*;
using MemSize = decltype(sizeof(MemUnit)); // Should always be 1 byte
class MemBuffer
{
Uptr<MemUnit[]> buffer;
MemRange range;
MemBuffer(MemSize mSize) : ...
{
// initialize buffer from mSize
}
};
class PreAllocatorChunk
{
protected:
MemSize chunkSize;
MemBuffer buffer;
std::stack<MemRange> available;
public:
PreAllocatorChunk(MemSize mChunkSize, unsigned int mChunks) : ...
{
// Add "chunks" to to available...
}
template<typename T, typename... TArgs> T* create(TArgs&&... mArgs)
{
// create on first "chunk" using placement new
auto toUse(available.top().begin); available.pop();
return new (toUse) T{std::forward<TArgs>(mArgs)...};
}
};
More pre-allocation utilities are available:
PreAllocatorDynamic: pre-allocates a big buffer, then, when creating an object, splits the buffer in two parts:
[buffer start, buffer start + obj size)
[buffer start + obj size, buffer end)
When an object is destroyed, its occupied memory range is set as "available". If during creation of a new object no big enough "chunk" is found, the pre-allocator tries to unify contiguous memory chunks before throwing a runtime exception. This pre-allocator is sometimes faster than new/delete, but it greatly depends on the size of pre-allocated buffer.
PreAllocatorStatic<T>: inherited from PreAllocatorChunk. Size of a chunk is equal to sizeof(T). Fastest pre-allocator, less flexible. Almost always faster than new/delete.
One of your issues can be solved by allocating enough space in the vectors on their creation
For
vector<unique_ptr<Entity>> entities;
provide enough space in the constructor
Manager::Manager() : entities(10000)
{
//...
}
Thus, you avoid reallocations and copying during later stages.
The second issue is the creation of your unique_ptr<Entity> pointers. Here, as you will always use default constructed objects, you could also use a pre-allocated pool of objects from which you create the pointers. Instead of calling new you would call an own class
class EntityPool
{
public:
EntityPool(unsigned int size = 10000) : pool(size), nextEntity(0)
{
}
Entity* getNext(void)
{
if (nextEntity != pool.size()) // if pool is exhausted create new
{
pool.emplace_back(Entity());
}
return pool[nextEntity++];
}
private:
vector<Entity> pool;
unsigned int nextEntity; // index into the vector to the next Entity
};
struct Manager
{
vector<unique_ptr<Entity>> entities;
Entity& createEntity()
{
entities.emplace_back(entityPoolInstance.getNext());
return *result;
}
//...
Or you could wire in the standard 'placement new'. This allows you to allocate a big block of memory to construct (place) objects into as you choose. This will keep the block on the heap for as long as you need it, and allow you to allocate multiple short lived objects into this block instead of doing the costly allocations and de-allocations that just end up fragmenting the heap. There's a couple of gotcha's involved, but all in all its a REALLY simple solution without having to go down the custom memory manager route.
Here's an excellent treatment of removing some of the pitfalls and describing placement new in detail.
I've used data structures as simple as a stack to keep track of the next free block to allocate into: push the address of a block that's about to be deleted onto the stack. When allocating just pop the next free block off of the stack and use that as the arg to placement new. Super easy and super fast!
I have a program that contains a processing phase that needs to use a bunch of different object instances (all allocated on the heap) from a tree of polymorphic types, all eventually derived from a common base class.
As the instances may cyclically reference each other, and do not have a clear owner, I want allocated them with new, handle them with raw pointers, and leave them in memory for the phase (even if they become unreferenced), and then after the phase of the program that uses these instances, I want to delete them all at once.
How I thought to structure it is as follows:
struct B; // common base class
vector<unique_ptr<B>> memory_pool;
struct B
{
B() { memory_pool.emplace_back(this); }
virtual ~B() {}
};
struct D : B { ... }
int main()
{
...
// phase begins
D* p = new D(...);
...
// phase ends
memory_pool.clear();
// all B instances are deleted, and pointers invalidated
...
}
Apart from being careful that all B instances are allocated with new, and that noone uses any pointers to them after the memory pool is cleared, are there problems with this implementation?
Specifically I am concerned about the fact that the this pointer is used to construct a std::unique_ptr in the base class constructor, before the derived class constructor has completed. Does this result in undefined behaviour? If so is there a workaround?
In case you haven't already, familiarize yourself with Boost.Pool. From the Boost documentation:
What is Pool?
Pool allocation is a memory allocation scheme that is very fast, but
limited in its usage. For more information on pool allocation (also
called simple segregated storage, see concepts concepts and Simple Segregated Storage.
Why should I use Pool?
Using Pools gives you more control over how memory is used in your
program. For example, you could have a situation where you want to
allocate a bunch of small objects at one point, and then reach a point
in your program where none of them are needed any more. Using pool
interfaces, you can choose to run their destructors or just drop them
off into oblivion; the pool interface will guarantee that there are no
system memory leaks.
When should I use Pool?
Pools are generally used when there is a lot of allocation and
deallocation of small objects. Another common usage is the situation
above, where many objects may be dropped out of memory.
In general, use Pools when you need a more efficient way to do unusual
memory control.
Which pool allocator should I use?
pool_allocator is a more general-purpose solution, geared towards
efficiently servicing requests for any number of contiguous chunks.
fast_pool_allocator is also a general-purpose solution but is geared
towards efficiently servicing requests for one chunk at a time; it
will work for contiguous chunks, but not as well as pool_allocator.
If you are seriously concerned about performance, use
fast_pool_allocator when dealing with containers such as std::list,
and use pool_allocator when dealing with containers such as
std::vector.
Memory management is tricky business (threading, caching, alignment, fragmentation, etc. etc.) For serious production code, well-designed and carefully optimized libraries are the way to go, unless your profiler demonstrates a bottleneck.
Your idea is great and millions of applications are already using it. This pattern is most famously known as «autorelease pool». It forms a base for ”smart” memory management in Cocoa and Cocoa Touch Objective-C frameworks. Despite the fact that C++ provides hell of a lot of other alternatives, I still think this idea got a lot of upside. But there are few things where I think your implementation as it stands may fall short.
The first problem that I can think of is thread safety. For example, what happens when objects of the same base are created from different threads? A solution might be to protect the pool access with mutually exclusive locks. Though I think a better way to do this is to make that pool a thread-specific object.
The second problem is invoking an undefined behavior in case where derived class's constructor throws an exception. You see, if that happens, the derived object won't be constructed, but your B's constructor would have already pushed a pointer to this to the vector. Later on, when the vector is cleared, it would try to call a destructor through a virtual table of the object that either doesn't exist or is in fact a different object (because new could reuse that address).
The third thing I don't like is that you have only one global pool, even if it is thread-specific, that just doesn't allow for a more fine grained control over the scope of allocated objects.
Taking the above into account, I would do a couple of improvements:
Have a stack of pools for more fine-grained scope control.
Make that pool stack a thread-specific object.
In case of failures (like exception in derived class constructor), make sure the pool doesn't hold a dangling pointer.
Here is my literally 5 minutes solution, don't judge for quick and dirty:
#include <new>
#include <set>
#include <stack>
#include <cassert>
#include <memory>
#include <stdexcept>
#include <iostream>
#define thread_local __thread // Sorry, my compiler doesn't C++11 thread locals
struct AutoReleaseObject {
AutoReleaseObject();
virtual ~AutoReleaseObject();
};
class AutoReleasePool final {
public:
AutoReleasePool() {
stack_.emplace(this);
}
~AutoReleasePool() noexcept {
std::set<AutoReleaseObject *> obj;
obj.swap(objects_);
for (auto *p : obj) {
delete p;
}
stack_.pop();
}
static AutoReleasePool &instance() {
assert(!stack_.empty());
return *stack_.top();
}
void add(AutoReleaseObject *obj) {
objects_.insert(obj);
}
void del(AutoReleaseObject *obj) {
objects_.erase(obj);
}
AutoReleasePool(const AutoReleasePool &) = delete;
AutoReleasePool &operator = (const AutoReleasePool &) = delete;
private:
// Hopefully, making this private won't allow users to create pool
// not on stack that easily... But it won't make it impossible of course.
void *operator new(size_t size) {
return ::operator new(size);
}
std::set<AutoReleaseObject *> objects_;
struct PrivateTraits {};
AutoReleasePool(const PrivateTraits &) {
}
struct Stack final : std::stack<AutoReleasePool *> {
Stack() {
std::unique_ptr<AutoReleasePool> pool
(new AutoReleasePool(PrivateTraits()));
push(pool.get());
pool.release();
}
~Stack() {
assert(!stack_.empty());
delete stack_.top();
}
};
static thread_local Stack stack_;
};
thread_local AutoReleasePool::Stack AutoReleasePool::stack_;
AutoReleaseObject::AutoReleaseObject()
{
AutoReleasePool::instance().add(this);
}
AutoReleaseObject::~AutoReleaseObject()
{
AutoReleasePool::instance().del(this);
}
// Some usage example...
struct MyObj : AutoReleaseObject {
MyObj() {
std::cout << "MyObj::MyObj(" << this << ")" << std::endl;
}
~MyObj() override {
std::cout << "MyObj::~MyObj(" << this << ")" << std::endl;
}
void bar() {
std::cout << "MyObj::bar(" << this << ")" << std::endl;
}
};
struct MyObjBad final : AutoReleaseObject {
MyObjBad() {
throw std::runtime_error("oops!");
}
~MyObjBad() override {
}
};
void bar()
{
AutoReleasePool local_scope;
for (int i = 0; i < 3; ++i) {
auto o = new MyObj();
o->bar();
}
}
void foo()
{
for (int i = 0; i < 2; ++i) {
auto o = new MyObj();
bar();
o->bar();
}
}
int main()
{
std::cout << "main start..." << std::endl;
foo();
std::cout << "main end..." << std::endl;
}
Hmm, I needed almost exactly the same thing recently (memory pool for one phase of a program that gets cleared all at once), except that I had the additional design constraint that all my objects would be fairly small.
I came up with the following "small-object memory pool" -- perhaps it will be of use to you:
#pragma once
#include "defs.h"
#include <cstdint> // uintptr_t
#include <cstdlib> // std::malloc, std::size_t
#include <type_traits> // std::alignment_of
#include <utility> // std::forward
#include <algorithm> // std::max
#include <cassert> // assert
// Small-object allocator that uses a memory pool.
// Objects constructed in this arena *must not* have delete called on them.
// Allows all memory in the arena to be freed at once (destructors will
// be called).
// Usage:
// SmallObjectArena arena;
// Foo* foo = arena::create<Foo>();
// arena.free(); // Calls ~Foo
class SmallObjectArena
{
private:
typedef void (*Dtor)(void*);
struct Record
{
Dtor dtor;
short endOfPrevRecordOffset; // Bytes between end of previous record and beginning of this one
short objectOffset; // From the end of the previous record
};
struct Block
{
size_t size;
char* rawBlock;
Block* prevBlock;
char* startOfNextRecord;
};
template<typename T> static void DtorWrapper(void* obj) { static_cast<T*>(obj)->~T(); }
public:
explicit SmallObjectArena(std::size_t initialPoolSize = 8192)
: currentBlock(nullptr)
{
assert(initialPoolSize >= sizeof(Block) + std::alignment_of<Block>::value);
assert(initialPoolSize >= 128);
createNewBlock(initialPoolSize);
}
~SmallObjectArena()
{
this->free();
std::free(currentBlock->rawBlock);
}
template<typename T>
inline T* create()
{
return new (alloc<T>()) T();
}
template<typename T, typename A1>
inline T* create(A1&& a1)
{
return new (alloc<T>()) T(std::forward<A1>(a1));
}
template<typename T, typename A1, typename A2>
inline T* create(A1&& a1, A2&& a2)
{
return new (alloc<T>()) T(std::forward<A1>(a1), std::forward<A2>(a2));
}
template<typename T, typename A1, typename A2, typename A3>
inline T* create(A1&& a1, A2&& a2, A3&& a3)
{
return new (alloc<T>()) T(std::forward<A1>(a1), std::forward<A2>(a2), std::forward<A3>(a3));
}
// Calls the destructors of all currently allocated objects
// then frees all allocated memory. Destructors are called in
// the reverse order that the objects were constructed in.
void free()
{
// Destroy all objects in arena, and free all blocks except
// for the initial block.
do {
char* endOfRecord = currentBlock->startOfNextRecord;
while (endOfRecord != reinterpret_cast<char*>(currentBlock) + sizeof(Block)) {
auto startOfRecord = endOfRecord - sizeof(Record);
auto record = reinterpret_cast<Record*>(startOfRecord);
endOfRecord = startOfRecord - record->endOfPrevRecordOffset;
record->dtor(endOfRecord + record->objectOffset);
}
if (currentBlock->prevBlock != nullptr) {
auto memToFree = currentBlock->rawBlock;
currentBlock = currentBlock->prevBlock;
std::free(memToFree);
}
} while (currentBlock->prevBlock != nullptr);
currentBlock->startOfNextRecord = reinterpret_cast<char*>(currentBlock) + sizeof(Block);
}
private:
template<typename T>
static inline char* alignFor(char* ptr)
{
const size_t alignment = std::alignment_of<T>::value;
return ptr + (alignment - (reinterpret_cast<uintptr_t>(ptr) % alignment)) % alignment;
}
template<typename T>
T* alloc()
{
char* objectLocation = alignFor<T>(currentBlock->startOfNextRecord);
char* nextRecordStart = alignFor<Record>(objectLocation + sizeof(T));
if (nextRecordStart + sizeof(Record) > currentBlock->rawBlock + currentBlock->size) {
createNewBlock(2 * std::max(currentBlock->size, sizeof(T) + sizeof(Record) + sizeof(Block) + 128));
objectLocation = alignFor<T>(currentBlock->startOfNextRecord);
nextRecordStart = alignFor<Record>(objectLocation + sizeof(T));
}
auto record = reinterpret_cast<Record*>(nextRecordStart);
record->dtor = &DtorWrapper<T>;
assert(objectLocation - currentBlock->startOfNextRecord < 32768);
record->objectOffset = static_cast<short>(objectLocation - currentBlock->startOfNextRecord);
assert(nextRecordStart - currentBlock->startOfNextRecord < 32768);
record->endOfPrevRecordOffset = static_cast<short>(nextRecordStart - currentBlock->startOfNextRecord);
currentBlock->startOfNextRecord = nextRecordStart + sizeof(Record);
return reinterpret_cast<T*>(objectLocation);
}
void createNewBlock(size_t newBlockSize)
{
auto raw = static_cast<char*>(std::malloc(newBlockSize));
auto blockStart = alignFor<Block>(raw);
auto newBlock = reinterpret_cast<Block*>(blockStart);
newBlock->rawBlock = raw;
newBlock->prevBlock = currentBlock;
newBlock->startOfNextRecord = blockStart + sizeof(Block);
newBlock->size = newBlockSize;
currentBlock = newBlock;
}
private:
Block* currentBlock;
};
To answer your question, you're not invoking undefined behaviour since nobody is using the pointer until the object is fully constructed (the pointer value itself is safe to copy around until then). However, it's a rather intrusive method, as the object(s) themselves need to know about the memory pool. Additionally, if you're constructing a large number of small objects, it would likely be faster to use an actual pool of memory (like my pool does) instead of calling out to new for every object.
Whatever pool-like approach you use, be careful that the objects are never manually deleteed, because that would lead to a double free!
I still think this is an interesting question without a definitive reply, but please let me break it down into the different questions you are actually asking:
1.) Does inserting a pointer to a base class into a vector before initialisation of a subclass prevent or cause issues with retrieving inherited classes from that pointer. [slicing for example.]
Answer: No, so long as you are 100% sure of the relevant type that is being pointed to, this mechanism does not cause these issues however note the following points:
If the derived constructor fails, you are left with an issue later when you are likely to have a dangling pointer at least sitting in the vector, as that address space it [the derived class] thought it was getting would be freed to the operating environment on failure, but the vector still has the address as being of the base class type.
Note that a vector, although kind of useful, is not the best structure for this, and even if it was, there should be some inversion of control involved here to allow the vector object to control initialisation of your objects, so that you have awareness of success/failure.
These points lead to the implied 2nd question:
2.) Is this a good pattern for pooling?
Answer: Not really, for the reasons mentioned above, plus others (Pushing a vector past it's end point basically ends up with a malloc which is unnecessary and will impact performance.) Ideally you want to use a pooling library, or a template class, and even better, separate the allocation/de-allocation policy implementation away from the pool implementation, with a low level solution already being hinted at, which is to allocate adequate pool memory from pool initialisation, and then use this using pointers to void from within the pool address space (See Alex Zywicki's solution above.) Using this pattern, the pool destruction is safe as the pool which will be contiguous memory can be destroyed en masse without any dangling issues, or memory leaks through losing all references to an object (losing all reference to an object whose address is allocated through the pool by the storage manager leaves you with dirty chunk/s, but will not cause a memory leak as it is managed by the pool implementation.
In the early days of C/C++ (before mass proliferation of the STL), this was a well discussed pattern and many implementations and designs can be found out there in good literature: As an example:
Knuth (1973 The art of computer programming: Multiple volumes), and for a more complete list, with more on pooling, see:
http://www.ibm.com/developerworks/library/l-memory/
The 3rd implied question seems to be:
3) Is this a valid scenario to use pooling?
Answer: This is a localised design decision based on what you are comfortable with, but to be honest, your implementation (no controlling structure/aggregate, possibly cyclic sharing of sub sets of objects) suggests to me that you would be better off with a basic linked list of wrapper objects, each of which contains a pointer to your superclass, used only for addressing purposes. Your cyclical structures are built on top of this, and you simply amend/grow shrink the list as required to accommodate all of your first class objects as required, and when finished, you can then easily destroy them in effectively an O(1) operation from within the linked list.
Having said that, I would personally recommend that at this time (when you have a scenario where pooling does have a use and so you are in the right mind-set) to carry out the building of a storage management/pooling set of classes that are paramaterised/typeless now as it will hold you in good stead for the future.
This sounds what I have heard called a Linear Allocator.
I will explain the basics of how I understand how it works.
Allocate a block of memory using ::operator new(size);
Have a void* that is your Pointer to the next free space in memory.
You will have an alloc(size_t size) function that will give you a pointer to the location in the block from step one for you to construct on to using Placement New
Placement new looks like... int* i = new(location)int(); where location is a void* to a block of memory you alloced from the allocator.
when you are done with all of your memory you will call a Flush() function that will dealloc the memory from the pool or at least wipe the data clean.
I programmed one of these recently and i will post my code here for you as well as do my best to explain.
#include <iostream>
class LinearAllocator:public ObjectBase
{
public:
LinearAllocator();
LinearAllocator(Pool* pool,size_t size);
~LinearAllocator();
void* Alloc(Size_t size);
void Flush();
private:
void** m_pBlock;
void* m_pHeadFree;
void* m_pEnd;
};
don't worry about what i'm inheriting from. i have been using this allocator in conjunction with a memory pool. but basically instead of getting the memory from operator new i am getting memory from a memory pool. the internal workings are the same essentially.
Here is the implementation:
LinearAllocator::LinearAllocator():ObjectBase::ObjectBase()
{
m_pBlock = nullptr;
m_pHeadFree = nullptr;
m_pEnd=nullptr;
}
LinearAllocator::LinearAllocator(Pool* pool,size_t size):ObjectBase::ObjectBase(pool)
{
if (pool!=nullptr) {
m_pBlock = ObjectBase::AllocFromPool(size);
m_pHeadFree = * m_pBlock;
m_pEnd = (void*)((unsigned char*)*m_pBlock+size);
}
else{
m_pBlock = nullptr;
m_pHeadFree = nullptr;
m_pEnd=nullptr;
}
}
LinearAllocator::~LinearAllocator()
{
if (m_pBlock!=nullptr) {
ObjectBase::FreeFromPool(m_pBlock);
}
m_pBlock = nullptr;
m_pHeadFree = nullptr;
m_pEnd=nullptr;
}
MemoryBlock* LinearAllocator::Alloc(size_t size)
{
if (m_pBlock!=nullptr) {
void* test = (void*)((unsigned char*)m_pEnd-size);
if (m_pHeadFree<=test) {
void* temp = m_pHeadFree;
m_pHeadFree=(void*)((unsigned char*)m_pHeadFree+size);
return temp;
}else{
return nullptr;
}
}else return nullptr;
}
void LinearAllocator::Flush()
{
if (m_pBlock!=nullptr) {
m_pHeadFree=m_pBlock;
size_t size = (unsigned char*)m_pEnd-(unsigned char*)*m_pBlock;
memset(*m_pBlock,0,size);
}
}
This code is fully functional except for a few lines which will need to be changed because of my inheritance and use of the memory pool. but I bet you can figure out what needs to change and just let me know if you need a hand changing the code. This code has not been tested in any sort of professional manor and is not guaranteed to be thread safe or anything fancy like that. i just whipped it up and thought i could share it with you since you seemed to need help.
I also have a working implementation of a fully generic memory pool if you think it may help you. I can explain how it works if you need.
Once again if you need any help let me know. Good luck.
I have a vector with raw pointers (no, I cannot use smart pointers) and I want to add items to the list in a for loop. I've made a little trial project, and I wondered if this is considered good C++ code in terms of pointer management.
Please only consider raw pointer management, I am not interested in smart pointers for this particular problem I'm trying to solve.
A simple object:
class Request
{
public:
std::string name;
};
std::vector<Request*> requests;
for (int i = 0; i < 5; i++)
{
std::stringstream ss;
ss << "elemenent ";
ss << i;
std::string s = ss.str();
Request* req = new Request();
req->name = s;
requests.push_back(req);
}
EDIT:
So the problem I am trying to solve is adding the DOMNode* to a vector from this library.
I'm starting to get the feeling that trying to write a wrapper for the parts I need from this library for my project, is a bad idea. Or maybe the library is no good?
I haven't got it to work properly using smart_ptr, if anybody out there has, then I'd like to hear about it.
Well, this leaks memory, so it is bad. Can you use a Pointer Container?
The reason this code leaks is because you create objects on the heap using new, but you never call delete on them.
As for you comment, if you have an object that manually manages some resource, you need The Big Three.
I'll consider that you have a loop, at the end of the method, to call delete on each member of the vector.
There are still issues, specifically exception safety issues.
If anything throws between the creation of the Request and its registration in the vector, you've lost the memory. One solution is to temporarily use a scoped_ptr to hold on the memory, push_back with ptr.get() and then call the release method since now the memory is owned by the vector.
If anything throws between the point when you have created the items in the vector and the point you destroy them, you need to catch the exception, destroy the items, and then rethrow.
There might be others, but RAII has been invented for a reason, it's really difficult to do without (correctly...)
If you cannot use smart pointers, then use boost::ptr_vector.
Note that if you are using TinyXml, memory management in XmlNode is probably dictated by the library - recent history iirc is that many of your problems are associated with properly understanding the memory ownership and release paradigm for this library.
What memory management do I need to cleanup when using TinyXml for C++?
What is the best open XML parser for C++?
If you are not able (or allowed) to use smart pointers, probably you could make use of a simple memory manager like this:
template <class T>
class MemManager
{
public:
typedef std::vector<T*> Vec;
~MemManager ()
{
size_t sz = v_.size ();
for (size_t i = 0; i < sz; ++i)
delete v_[i];
}
T* pushNewObject ()
{
T* t = NULL;
try
{
t = new T;
if (t != NULL)
v_.push_back(t);
}
catch (std::bad_alloc& ex) { /* handle ex */ }
return t;
}
const Vec& objects() const { return v_; }
private:
Vec v_;
};
// test
{
MemManager<Request> mm;
for (int i = 0; i < 5; i++)
{
std::stringstream ss;
ss << "elemenent ";
ss << i;
std::string s = ss.str();
Request* req = mm.pushNewObject();
req->name = s;
}
} // all Request objects will be deleted here when
// the MemManager object goes out of scope.
A quick improvement could be to derive a class RequestVector from std::vector<Request*>, add a ClearRequests method (which deletes all the Request objects and clears the vector) and and make it's destructor call ClearRequests.
(Actually aggregating the vector in RequestVector could be a better choice, but a derived class is faster done).
Profiling some code that heavily uses shared_ptrs, I discovered that reset() was surprisingly expensive.
For example:
struct Test {
int i;
Test() {
this->i = 0;
}
Test(int i) {
this->i = i;
}
} ;
...
auto t = make_shared<Test>(1);
...
t.reset(somePointerToATestObject);
Tracing the reset() in the last line (under VC++ 2010), I discovered that it creates a new reference-counting object.
Is there a cheaper way, that reuses the existing ref-count and does not bother the heap?
In the general case, you can't reuse the existing ref count because there may be other shared_ptrs or weak_ptrs using it.
If you can create somePointerToATestObject using make_shared(), then the implementation may use a single heap allocation for both the ref counts and the object. That will save you one of the heap allocations.