   [C++] Memory management (again!)
  Currently I have an, as I would say, almost-neat memory management. It uses reference counting which works great.To not worry about retain/release or gain/lose (like new/delete), I implemented a smart pointer (thanks Rip-off ;-)). The problem with the smart pointer mainly is how you initialise an object, since we do want to use the constructor (or not necessarily?).Currently I use the following. Left side is declaration of a smart pointer (typedef), right side is initialisation of the class on the stack, passed to the smart pointer which allocates it on the heap:DaevsGUI::Textures::CoronaPointer atlas = DaevsGUI::Textures::Corona("gui.png");Now comes the difficult point: the smart pointer makes sure the memory is allocates on the libraries heap! Thus I can't let library users allocate the memory themselves (executable heap) and use that in the library...which is frustrating.So currently, an object on the stack is allocated, then within the smart pointer it copies and allocates the object on the heap. That is 2 allocations and 1 copy. Ideally this would be just 1 allocation.Possible solutions: - Define a new/delete operator (or something that looks like it) within the libraries namespace, which allocates on the libraries heap - Leave it as it is... - Do not support DLL, only static linking... - Make sure everything is allocated on the executables heap instead of the library's (not sure how to implement that...)Only the first option sounds reasonable (and possible the last)...though I don't like overloading the new/delete operator within a namespace, if it's even possible. Defining a function called allocate() would give the same problem! The stack object is first created then copied...Foo *f(const Foo &foo) // this function will be templated{    return new Foo(foo);/* since it's templated, this should call untemplated functions to allocate  (to make sure its on the libs heap), by making a static create() member  function per class for example */}int main(){    Foo *foo = f(Foo());    delete foo;}// Foo is constructed, then copy constructed, then deleted (in f), and again deleted (in main)Then the last option, how can I make sure code pre-compiled in the library, will use an allocater defined by the library user...? Function pointers? This option can be pretty neat actually, it also supports users adding their own memory managers, as Rip-off suggested me to implement.Thanks...it got a bit lengthy, sorry.   
Quote:Original post by DecriusNow comes the difficult point: the smart pointer makes sure the memory is allocates on the libraries heap! Thus I can't let library users allocate the memory themselves (executable heap) and use that in the library...which is frustrating.class Allocator{public:  virtual void* alloc(size_t) = 0;  virtual void free(void*) = 0;};DLL_EXPORT void setLibraryAllocator(Allocator* a);Quote:Original post by DecriusSo currently, an object on the stack is allocated, then within the smart pointer it copies and allocates the object on the heap. That is 2 allocations and 1 copy. Ideally this would be just 1 allocation.Wut? Do you even have enough stack memory around to hold a png image? What's wrong with allocating image data on the heap exactly?Quote:Original post by DecriusPossible solutions: - Define a new/delete operator (or something that looks like it) within the libraries namespace, which allocates on the libraries heap - Leave it as it is... - Do not support DLL, only static linking... - Make sure everything is allocated on the executables heap instead of the library's (not sure how to implement that...)or use a virtual destructor. or use a custom allocator strategy (as per the source above). Quote:Original post by DecriusOnly the first option sounds reasonable (and possible the last)...though I don't like overloading the new/delete operator within a namespace, if it's even possible. Uhm, you don't wan't to be overloading the global new/delete. Nothing wrong with overloading it on a class by class basis and making it call a custom allocator (instead of malloc/free). Quote:Original post by DecriusDefining a function called allocate() would give the same problem! The stack object is first created then copied...That code is worthy of a WTF award. I think you may have confused yourself. Quote:Then the last option, how can I make sure code pre-compiled in the library, will use an allocater defined by the library user...? Function pointers? This option can be pretty neat actually, it also supports users adding their own memory managers, as Rip-off suggested me to implement.uhm. Yes. Or an interface. Or... class DLL_EXPORT Foo{protected:  Foo();  ~Foo();public:  static Foo* create() { return new Foo(); }  static void destroy(Foo* f) { delete f; }};or.... // in dllclass DLL_EXPORT Foo{protected:  Foo();public:  virtual ~Foo();  static Foo* create() { return new Foo(); }};// in exeFoo* f = Foo::create();delete f;or....// in dllclass DLL_EXPORT Foo{public:  Foo();};// in exeFoo* f = new Foo();delete f;;Quote:Now comes the difficult point: the smart pointer makes sure the memory is allocates on the libraries heap! Thus I can't let library users allocate the memory themselves (executable heap) and use that in the library...which is frustrating.IMHO, you don't bother with it.DLL provides plain C malloc and free versions for objects you wish to allocate. Your own API then implements those calls inside factory.// library APITexture * alloc_texture(...);void fre_texture(Texture * texture);...// User API:struct LibraryDeleter {  void operator()(Texture * t) { free_texture(t); }};typedef boost::shared_ptr<Texture, LibraryDeleter> TexturePtr;TexturePtr loadTexture(const char * foo) {  return TexturePtr(alloc_texture(foo));};PS: the shared_ptr API is from the top of my head, I don't exactly recall how boost does it.   ;Quote:Original post by RobTheBloke*** First snippet ***Sounds good, thanks.Quote:Original post by RobTheBlokeWut? Do you even have enough stack memory around to hold a png image? What's wrong with allocating image data on the heap exactly?These are of course stored as pointers to the heap within the classes.Quote:Original post by RobTheBlokeor use a virtual destructorHow would this solve the problem?Quote:Original post by RobTheBlokeThat code is worthy of a WTF award. I think you may have confused yourself.No, this makes sure f() (DLL) allocates the memory on the DLL's heap, not the executable. Quote:Original post by RobTheBlokeuhm. Yes. Or an interface. Or... *** Second snippet ***That would make sure it's on the DLL yes, but doesn't allow passing parameters to the constructor.Quote:Original post by RobTheBlokeor.... *** Third snippet ***Would delete DLL heap from the executable.Quote:Original post by RobTheBlokeor....*** Fourth snippet ***Would mean I implement that allocator interface to make sure everything is on the executables heap.   ;  Right, I did a quick test, but I can't seem to make a function that works like 'new' but doesn't overload it...class Allocator{public:    virtual void *allocate(size_t size);    virtual void free(void *pointer);};void *Allocator::allocate(size_t size){    void *pointer = malloc(size);    if (!pointer)    {   throw std::bad_alloc();    }    return pointer;}void Allocator::free(void *pointer){    free(pointer);}int main(){    Allocator allocator;    Foo *pointer = allocator.allocate(Foo());    allocator.free(pointer);}E:\C\Performance\main.cpp: In function `int main()':E:\C\Performance\main.cpp:62: error: no matching function for call to `Allocator::allocate(Foo)'E:\C\Performance\main.cpp:44: note: candidates are: virtual void* Allocator::allocate(size_t);  The functions/type you wrote aren't magic. If you write a function that takes a size_t argument, why would passing it a Foo instance work?In C++, "new" is a two stage process. One is obtaining memory, using "operator new" usually. The second is constructing an instance in this memory. You can separate these steps, using placement new for the second step. Placement new constructs an object in preallocated memory.int main(){    void *memory = operator new(sizeof(Foo));    Foo *foo = new (memory) Foo( /* ... */ );    // ...}Obviously this can cause resource leaks, because we must free the memory (using operator delete), but also call Foo's destructor. This is the reason why calling a destructor is possible, but rare, in C++:int main(){    void *memory = operator new(sizeof(Foo));    Foo *foo = new (memory) Foo( /* ... */ );    // ...    foo->~Foo();    operator delete(memory);}So, to support user allocators, you just substitute operator new() and operator delete() for the user allocation functions.   ;  Nice one rip-off, I figured out the following:// interface with default memory handling on the DLL heapclass Memory{public:    virtual void *allocate(size_t size);    virtual void free(void *pointer);};void *Memory::allocate(size_t size){    return operator new(size);}void Memory::free(void *pointer){    operator delete(pointer);}Memory _memory;// heap on executable side, custom user defined memory handlerclass UserMemory: public Memory{public:    void *allocate(size_t size);    void free(void *pointer);};void *UserMemory::allocate(size_t size){    return operator new(size);}void UserMemory::free(void *pointer){    operator delete(pointer);}UserMemory _usermemory;Memory *memory = &_usermemory; // set which memory handler to use// hmm#define allocate(object) new (memory->allocate(sizeof(object))) objecttemplate <class T>inlinevoid deallocate(T *pointer){    pointer->~T();    memory->free(pointer);}int main(){    std::cerr << sizeof(Memory); // to my surprise this is 4 not 0!    Foo *foo = allocate(Foo(5));    deallocate(foo);}Not bad ;-), except that I have to use a define in order not to copy construct the object (which happens for a normal function), I hope there is a better alternative for that.Also, there's a few global variables here, I hope that's not too much of a problem...   ;Quote:Quote:Original post by RobTheBlokeor use a virtual destructorHow would this solve the problem?When you call delete on the base class pointer, it calls the derived classes version, which is defined in the DLL. Quote:Quote:Original post by RobTheBlokeThat code is worthy of a WTF award. I think you may have confused yourself.No, this makes sure f() (DLL) allocates the memory on the DLL's heap, not the executable. Was referring to the rather *strange* use of the copy ctor. (which is utterly redundant.Quote:Quote:Original post by RobTheBlokeuhm. Yes. Or an interface. Or... *** Second snippet ***That would make sure it's on the DLL yes, but doesn't allow passing parameters to the constructor.yes it does. Nothing stopping you changing the function parameters to Create() and passing them to the ctor. Quote:Quote:Original post by RobTheBlokeor.... *** Third snippet ***Would delete DLL heap from the executable.No it won't.Quote:Nice one rip-off, I figured out the following:Oh god. That's even worse. For a start, the code will not work with:class Foo{public:  Foo() {}};Second, it will not work with arrays. Third, it's more complicated than it needs to be. 1. Define an interface for the allocator. Note that this should be an interface, and not just a class with virtual functions// interface with default memory handling on the DLL heapclass Memory{public:    virtual void *allocate(size_t size)=0;    virtual void free(void *pointer)=0;};2. Some macros for new/delete :#define  DEFINE_MEMORY_OPERATORS \ void* operator new(size_t s); \ void* operator new[](size_t s); \ void operator delete(void* s); \ void operator delete[](void* s);#define  IMPLEMENT_MEMORY_OPERATORS(CLASS) \ extern Memory* gAllocator; \ void* CLASS :: operator new(size_t s) { return gAllocator->alloc(s); } \ void* CLASS :: operator new[](size_t s){return gAllocator->alloc(s); } \  void CLASS :: operator delete(void* ptr) { gAllocator->free(ptr); } \ void CLASS :: operator delete[](void* ptr) { gAllocator->free(ptr); }3. The dll source code:// in header:namespace MyDll{  EXPORT void setAllocator(Memory* alloc);}// in source filenamepsace MyDll{  Memory* gAllocator=0;  EXPORT void setAllocator(Memory* alloc)  {    gAllocator = alloc;  }}4. For each class in the dll// in headernamespace MyDll{  class Export Foo {  public:    Foo(int an_argument);   DEFINE_MEMORY_OPERATORS;  };}// in source file:namespace MyDll{  IMPLEMENT_MEMORY_OPERATORS(Foo)}5. Finally in you exe:// heap on executable side, custom user defined memory handlerclass UserMemory: public Memory{public:    void *allocate(size_t size);    void free(void *pointer);};void *UserMemory::allocate(size_t size){    return ::malloc(size);}void *UserMemory::free(void *pointer){    return ::free(pointer);}UserMemory gMainAllocator;void main(){  MyDll::setAllocator(&gMainAllocator);  // all allocated in the exe by the allocator registered with the DLL  Foo* f = new Foo(5);  delete f;};  You can implement a Java/C# like "object reference" semantics in C++ if that is what you need.Ie, instead of:DaevsGUI::Textures::CoronaPointer atlas = DaevsGUI::Textures::Corona("gui.png");you can do:DaevsGUI::Textures::Corona atlas("gui.png");where DaevsGUI::Textures::Corona is a class that wraps a smart pointer (say, a boost::shared_ptr) to your Corona_pImpl class.The DaevsGUI::Textures::Corona class delegates everything -- from construction to any other operators -- to the pImpl class.  The DaevsGUI::Textures::Corona class exists on the stack, or wherever the user of the class wants it to exist -- memory wise, it consists of a single shared pointer object.  The methods should generally check if the pImpl is null, and if so, fail gracefully.This generates pointer like semantics.You can extend this to value like semantics via implementing copy on write.  Have the copy on write code check the reference count of the pImpl -- if it is 1, it doesn't have to do a copy.  If it is > 1, it does a copy, then does the write.  With a bit of care this can be made thread-safe (between instances of Corona, not multiple threads accessing the same Corona).Of course you can do this with the CursorPointer class itself, but the idea is that you can hide the fact that most of the memory is hidden in the pImpl, and have the users simply carry around what behave like value-constructs and never have to worry about where the memory is hiding.;Quote:Original post by NotAYakkYou can implement a Java/C# like "object reference" semantics in C++ if that is what you need.Ie, instead of:DaevsGUI::Textures::CoronaPointer atlas = DaevsGUI::Textures::Corona("gui.png");you can do:DaevsGUI::Textures::Corona atlas("gui.png");where DaevsGUI::Textures::Corona is a class that wraps a smart pointer (say, a boost::shared_ptr) to your Corona_pImpl class.The DaevsGUI::Textures::Corona class delegates everything -- from construction to any other operators -- to the pImpl class.  The DaevsGUI::Textures::Corona class exists on the stack, or wherever the user of the class wants it to exist -- memory wise, it consists of a single shared pointer object.  The methods should generally check if the pImpl is null, and if so, fail gracefully.This generates pointer like semantics.You can extend this to value like semantics via implementing copy on write.  Have the copy on write code check the reference count of the pImpl -- if it is 1, it doesn't have to do a copy.  If it is > 1, it does a copy, then does the write.  With a bit of care this can be made thread-safe (between instances of Corona, not multiple threads accessing the same Corona).Of course you can do this with the CursorPointer class itself, but the idea is that you can hide the fact that most of the memory is hidden in the pImpl, and have the users simply carry around what behave like value-constructs and never have to worry about where the memory is hiding.That sounds very cool, but would that mean I have to write a wrapper class for every implementation class to support the constructor arguments? Or can that be done more general?   