Sign in to follow this  
RonHiler

Override of placement new

Recommended Posts

RonHiler    214
Hey guys. In this bit of code, I have used a placement new

[code]
void Push_Back(AType &Element)
{
if (ArraySize == ArrayCapacity)
Grow();
//create a copy of the item (use placement new to put it in the array memory area)
AType *Loc = MemoryMgr.GetPointer<AType>(ENGINEPOOL, MemHandle, ArraySize);
AType *TempElement = new (Loc) AType(Element);
ArraySize++;
}
[/code]

In the memory manager class, I have overridden the placement new as such:

inline void* _cdecl operator new(std::size_t, void *loc) {return loc;}

However, this is not being called. Instead, the regular (non-overloaded) placement new is being called.

All my other overloaded new functions are being called as they should, but not this one. What am I doing wrong here?

Share this post


Link to post
Share on other sites
I think that if you overload a placement new in the memory manager class, it will only be called when doing a placement new of a memory manager object.

So, in your case, AType needs to provide the operator new (size_t, void *).

[code]
struct x
{
void *operator new(size_t x, void *y) { return y; }
};

struct y {};

int main()
{
void *buf = get_some_memory();

x *xx = new (buf) x; // this will call x::operator new

y *yy = new (buf) y; // this will call default operator new
}
[/code]

Share this post


Link to post
Share on other sites
RonHiler    214
[quote name='bbobak' timestamp='1302890580' post='4798849']
I think that if you overload a placement new in the memory manager class, it will only be called when doing a placement new of a memory manager object.[/quote]

Is that true even if they are declared globally? I know what you are saying is the case if the new operators are defined within a particular class, but these were defined global.

When I said they were defined in the memory manager class, that was a bit misleading. They are defined there (in the header for that class), but globally, not within the class. This is what it looks like:

[code]
#pragma once

#include "Hash.h"

namespace Enzyme
{
//some enums....
class MemoryManager
{
//all the class stuff...
};

extern "C" {DLLEXPORT extern MemoryManager MemoryMgr;}

//global overrides for new and delete operators
void* operator new(size_t size);
void* operator new[](size_t size);
void operator delete(void *p);
void operator delete[](void *p);
void* operator new(std::size_t size, const std::nothrow_t&);
void* operator new[](std::size_t size, const std::nothrow_t&);
void operator delete(void *p, const std::nothrow_t&);
void operator delete[](void *p, const std::nothrow_t&);
inline void* operator new(std::size_t, void *loc) {return loc;}
inline void* operator new[](std::size_t, void *loc) {return loc;}
inline void operator delete (void*, void*) { }
inline void operator delete[](void*, void*) { }
}
[/code]

The first 8 seem to work fine, they are called from anywhere in the engine. The last 4, for whatever reason, are not (and I'm only assuming that's the case, the only one I've verified as actually not being called is the first of the 4, but I presume the others are not going to be called either).

I read something on the internets about how you cannot override a placement new operator. Is that possibly what is going on here?

Share this post


Link to post
Share on other sites
Red Ant    471
Why would one want to override [b]placement [/b]new? :blink: I mean placement new is supposed to take a chunk of existing memory and use it to constuct an instance of something, right? So what could a reimplemented version do differently?

Share this post


Link to post
Share on other sites
A quick test on codepad gives me:

[code]

namespace tns
{
inline void *operator new(size_t t, void *p) { return p; }
}[/code]

[code]
Line 3: error: 'void* tns::operator new(size_t, void*)' may not be declared within a namespace
compilation terminated due to -Wfatal-errors.
[/code]

Share this post


Link to post
Share on other sites
RonHiler    214
[quote name='bbobak' timestamp='1302899220' post='4798907']
A quick test on codepad gives me:

[code]

namespace tns
{
inline void *operator new(size_t t, void *p) { return p; }
}[/code]

[code]
Line 3: error: 'void* tns::operator new(size_t, void*)' may not be declared within a namespace
compilation terminated due to -Wfatal-errors.
[/code]
[/quote]

Huh, that's weird. Works just fine in MSVC 2010. I'll try defining them outside the namespace and see if that makes a difference.

Share this post


Link to post
Share on other sites
RonHiler    214
Well, okay guys. Here's what I've come up with.

Taking the definitions out of the namespace has no effect whatsoever on the first 8 definitions. They work just the same either way (at least in MSVC, how they behave in codepad I've no idea). I went ahead and moved them out of the namespace, since that makes more sense anyway.

As for the other 4 definitions, if you move them outside a namespace, you get compilation errors (body already defined etc). Putting them inside a namespace, they don't get called at all (even a qualifier, e.g. Enzyme::new() doesn't work). So I think the conclusion is you simply cannot override these types globally (which is what my internet searching seems to have been suggesting). If I really want to override them, it would have to be done on a per class basis, I think.

Which is fine. The only real reason to overload a placement new is for diagnostics, and I can do that on a per class basis (I only really have one class that uses placement new at this point anyway).

So I've removed those 4 definitions, I'll let the default routines run for those cases.

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