Sign in to follow this  
Evil Steve

Override Placement New?

Recommended Posts

Evil Steve    2017
Hi all, I'm in the process of writing a memory manager, and I've run into a problem. I'm trying to use placement new like so:
void* pBuff = malloc(sizeof(PMemory));
PMemory* pMemory = ::new(pBuff) PMemory();



However, that gives me:
Quote:
pmemory.cpp(82) : error C2660: 'operator new' : function does not take 2 arguments
I've overridden the global operator new (and new[], delete and delete[]), but that's in another source file, so the compiler shouldn't be aware of it at all... Does anyone have any ideas what the hell's going on? Do I need to somehow override placement new as well? EDIT: The following project also causes the same problem. Am I just screwing up the syntax for placement new or something?
#include "malloc.h"

class PMemory
{
public:
	PMemory() {}
	~PMemory() {}
};


int main(int argc, char** argv[])
{
	void* pBuff = malloc(sizeof(PMemory));
	PMemory* pMemory = new(pBuff) PMemory();
	return 0;
}

Cheers, Steve

Share this post


Link to post
Share on other sites
Hnefi    386
void* pBuff = malloc(sizeof(PMemory));
PMemory* pMemory = ::new(pBuff) PMemory();


This looks very strange. Why are you trying to mix malloc and new? Mixing them is evil, you know.

Maybe this will work better:
void* pBuff = new char[sizeof(PMemory)];
PMemory* pMemory = ::new(pBuff)PMemory();

Or, safer code:
char mem[sizeof(PMemory)];
void* pBuff = mem;
PMemory* pMemory = ::new(pBuff)PMemory();

Share this post


Link to post
Share on other sites
Evil Steve    2017
Yeah, I'm aware of the problems with mixing new and malloc(). I have my reasons though [smile]

This is a memory manager, so obviously I can't call new (It would invoke the memory manager, which means an infinite loop then stack overflow), and I need to reference the object outside of the function, so an array isn't any good either. A static array would be ok, but that gives the same problem:

static char pBuff[sizeof(PMemory)];
PMemory* pMemory = new(pBuff) PMemory();


Share this post


Link to post
Share on other sites
dmail    116
This is the way I have done this in the past, it makes it much nicer to just create using new. Obviously this is a trimmed down version which has problems yet it shows what it is meant to.


#include <stdexcept>

struct Bar
{
Bar():bar(0){}
int bar;
};
struct Mem_manger
{
static Mem_manger* ptr()//ye ye a singleton just to make it nice and easy for the example
{
static Mem_manger* m_this(0);
if(!m_this)
{
m_this = new Mem_manger;
}
return m_this;
}
void* memory(size_t size)
{
//here you should see if you have a slot the correct size of bigger
//attach your header for slot
//remove the slot from the list etc
return m_buffer;
}
static void * operator new( size_t size )
{
return malloc( size );
}

static void operator delete( void * memory )
{
if ( !memory )
return;

free( memory );
}

private:
Mem_manger(){}
char m_buffer[sizeof(Bar)];//temp should get it from a buffer which is managed

};

void * operator new( size_t size, Mem_manger * heap )
{
return heap->memory(size);
}

void * operator new( size_t size )
{
void* ptr = operator new( size, Mem_manger::ptr() );
if(!ptr)throw std::bad_alloc("could not get the memory");
return ptr;
}


int main(int argc, char *argv[])
{

Bar* b = new Bar;

return 0;
}


Share this post


Link to post
Share on other sites
LorenzoGatti    4442
Original post by Hnefi

Or, safer code:
char mem[sizeof(PMemory)];
void* pBuff = mem;
PMemory* pMemory = ::new(pBuff)PMemory();


Safer? It looks like a textbook example of brutal stack smashing: if "pMemory" is copied back to the caller, the stack allocated "mem" goes out of scope and the object overlaps with arbitrary subsequent stack frames.
An allocated buffer, at worst, can only be leaked.
The only safe thing about this variant is that allocation "cannot fail" (unless the stack overflows, of course), but checking the result of malloc or operator new is more practical.

Share this post


Link to post
Share on other sites
Hnefi    386
Obviously, if the memory was to be used outside of the function in which it was called, it would have to be static. And obviously, it would have to be of limited size to prevent stack problems.

I assumed (correctly, I believe) that these are issues that the OP is competent enough to recognize on his own, without me having to go over every ramification of the method in detail.

Share this post


Link to post
Share on other sites
SiCrane    11839
Unfortunately, neither the static or stack based char array guarantees proper alignment, which means the placement new might die a messy death by SIGBUS or its moral equivalent for the platform the code gets run on.

Share this post


Link to post
Share on other sites
Zahlman    1682
Quote:
Original post by SiCrane
Unfortunately, neither the static or stack based char array guarantees proper alignment, which means the placement new might die a messy death by SIGBUS or its moral equivalent for the platform the code gets run on.


You could overallocate by (alignment size - 1) bytes and then round up?

Share this post


Link to post
Share on other sites
Evil Steve    2017
Alignment was something I forgot about until I read it in some link on placement new when I was investigating this. Does malloc() always align correctly then?

Share this post


Link to post
Share on other sites
SiCrane    11839
malloc() and ::operator new() are both guaranteed to return a memory block properly aligned for any type the compiler supports.

Share this post


Link to post
Share on other sites
SiCrane    11839
Quote:
Original post by Zahlman
You could overallocate by (alignment size - 1) bytes and then round up?

That's actually how functions like MSVC's _aligned_malloc() work. However, for static allocations, it's less wasteful to declare the memory block in a union with other types. Then the memory block will be guaranteed to be aligned to the alignment of the most restrictive type in the union. It's still pretty ugly either way.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this