views:

318

answers:

4

I've overloaded the global operator new/delete/new[]/delete[] but simple tests show that while my versions of new and delete are being called correctly, doing simple array allocations and deletes with new[] and delete[] causes the implementations in newaop.cpp and delete2.cpp to be called.

For example, this code

int* a = new int[10];

calls operator new[] in newaop.cpp, which in turn calls my version of operator new. So it seems they are globally overloaded but for some reason not the array versions. Is there something I'm missing?

EDIT: My implementation of the operators are in a separate project which is compiled into a library and linked to statically. In retrospect, this might have been useful to include in the original post, as it probably has something to do with this. Although I still can't figure out why only the array versions are affected.

A: 

operator new allocates one object and calls its constructor. new[] allocates n objects and calls n constructors.

edit: Having multiple new[] and delete[] overloads could be considered a bit of and odd one. How does the compiler know which one to link too? Any chance you could post your overloads? Also do yours get called if you don't link newaop and delete2 in (ie yours are the only implementations in the exe)?

Goz
I was referring to differences regarding my question. Sorry if I wasn't clear enough.
Flawe
Goz: You are allowed to replace certain functions ("replacement functions"), see 18.4.1.
Roger Pate
Im well aware you can ... but replacing them twice seems a bit odd ... Unless newaop and delete2 are CRT files, of course ... but some code would still be useful ...
Goz
newaop and delete2 seem to be visual studio specific and get linked into your code, it's not anything I've chosen. The reason why I didn't post any code is because it's scattered all over, which reminds me. My implementation of the operators are in a separate project which is compiled into a library and linked to statically. In retrospect, this might have been useful to include in the original post, as it probably has something to do with this. Although I still can't figure out why only the array versions are affected.
Flawe
Well you are gonna have to try because there is precious little we can say ... it SHOULD work ... it doesn't and without seeing code how can we work out why?
Goz
Ah, I didn't understand flippy as replacing them twice, just one single-object form and one array form.
Roger Pate
Well... turns out hes not ... still ... something is wrong ;)
Goz
+3  A: 

I don't know how you overloaded operator new[] but I just tried it with MSVC2008:

void* operator new[](size_t size)
{
  return 0;
}

int main()
{
  int* a = new int[5];
}

The code above effectively calls my faulty implementation of operator new[].

So here is my guess: you failed at overloading operator new[] for some reason and your program uses the compiler's version of operator new[] which relies on operator new to allocate the memory. Since you overloaded operator new, your implementation gets called.

Gregory Pakosz
Though since your faulty replacement violates the requirements for operator new[] and invokes undefined behavior, anything could happen! :P
Roger Pate
My purpose was just to step debug into my `operator new[]` that returns a null pointer. I didn't want to go into pasting a bullet-proof implementation here in my example so I chose to write one that is obviously buggy and cannot be considered as a take away :)
Gregory Pakosz
That's why I said it tongue-in-cheek. :P Invoking UB any time is bad, but can hide important issues in examples, like trying `new int[5]()` using the above, and I thought it worth pointing out that you can't actually implement new[] like this in C++.
Roger Pate
I don't see a problem with your overload, mine is similar. Since I use it for very specific reasons I don't want it to simulate the behavior of the standard one, e.g. I don't want my overload to throw or call the new handler.
Flawe
Actually, on allocation failure I just abort, since I assume that never happens for my application.
Flawe
flippy: You cannot, according to the C++ spec (see 18.4.1.1/3), avoid throwing on allocation failure in `operator new(size_t)`, but you're not required to call the new handler. If you want different behavior, then you need to use a different form of new, which includes the std::nothrow overload and any overload you want to write.
Roger Pate
Why don't you just set a new handler that aborts and use the default or nothrow operator new, then?
Roger Pate
You mean instead of overloading them? It's because I have a memory manager that does tracking and debugging. Also I'm using dlmalloc.
Flawe
A: 

You told us your code is buggy but didn't post any of it :vP . My guess would be that you used int as the argument of the overload rather than size_t. Some overloads might get called because the compiler decided to be tolerant in that instance.

Potatoswatter
A: 

Ok, I managed to crack this so am posting in case anyone else stumbles upon this.

The reason for the operator not being called was because my implementation was located in a library, not in the project which called the operators. In fact, since technically you only need to include an implementation of the operators, they are already globally defined, I only specified the implementation of the operators in a .cpp in my library (this was the wrong step). The code obviously only included the header files from the library and didn't ahve visibility to the implementations. Moreover, Visual Studio seems to have linked newaop.cpp and delete2.cpp into my application. These two files contain implementations for operator new[] and operator delete[] (bot not for regular new/delete!). This is most likely the reason why the compiler saw these two implementations and chose them over mine, which resided in a .cpp file in a library.

The solution to this was to move the implementation of my overloaded operators to a header file in the library which is directly included from my code.

Flawe
You should put this in the original question, or maybe mark it as the chosen answer (not sure if you can), because it'll just sit at the bottom of the page.--You shouldn't have to put the implementation of your overloads in headers. The standard requires that the default version be replaced by an implementation in your "program", which should include static libraries.
Potatoswatter
Yes, it does include libraries. The problem was that Visual Studio linked newaop.cpp and delete2.cpp which also included implementations fo those operators and the compiler chose them over mine. Since it only affected the array versions of the operators! The regular operators where defined in the exact same way and they worked.
Flawe