Search code examples
c++operator-overloadingmemory-managementnew-operatorallocation

a library forces global overloads of new/delete on me!


I'm maintaining a plugin (implemented as a dll) for a big closed source application. This has been working fine for years. However, with the latest update to it's SDK the vendor overloaded global operators new and delete. This causes lots of trouble for me. What happens is that my plugin allocates a string. I pass this string into a statically linked library which modifies it (changes it's length thus reallocating it). My application crashes.

The reason is of course, that the string lives on the vendor allocated custom heap. The statically linked library knows nothing about this heap and tries to use the default new/delete operators on that memory. Boom.

Now the question is: how can I keep my code clean and avoid using the vendor's operators? There is no conditional preprocessor macro. I can not avoid including the offending header since it contains 2000 lines more code I need for the plugin. I cannot pass the provided allocator into the other library since it does not provide any mechanisms for that. I have already bugged the vendor about it. I don't know what else I could try?

Addendum: After some heated debate I have managed to convince the vendor to remove the overloads again from the next version of the SDK. I have solved my immediate problem by simply hacking the current SDK and removing the overloads manually. Thanks for all the suggestions in this thread. They served as arguments and further "proof" of why the overloads were a bad idea in the first place.


Solution

  • If you're compiling in (via header inclusion) an overridden new/delete operator(s), then all calls in your code to new/delete will use them. There is no way to re-override it (link errors) or only partially override it, etc.

    It is bad form to override the global new/delete operators, at all. It's a bad idea. If you don't realize why it's a bad idea, you're not qualified to do so. If you do realize why it's a bad idea, you're qualified to do so, but you'll generally choose not to.

    Defining a global new/delete is exponentially more evil in a component you expect people to include directly into their project. It is your job as a customer to help the vendor doing this understand the seriousness of the situation, or stop being their customer.

    You can define a custom allocator type (see this link for a good tutorial on how to do so, the interface needed, etc) and use that exclusively with your STL types (it's a template argument).

    For shared_ptr, you need to do something a little different: it takes a deleter object as a parameter to the constructor if you don't want the default "delete p" behavior. This isn't a custom allocator; it's just a regular unary functor.