开发者

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.


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.


Isn't it possible to do this:

namespace evil{

#include "evil_header.h"

}

Then what evil_header declares as global new/delete becomes evil::new/evil::delete. I doubt this will play well if there are non-header definitions of things declared in evil_header though.


You can use another new in your namespace:

namespace MyNS {
    // Declare your new/delete operators here
    // and also declare a class implementing the same interface as std::allocator
    // using your newly created memory management functions.
    // Don't forget to put all your classes in the namespace.
    // (if you don't have one already)
}

Your can then use all STL classes, giving them your allocator type as template argument.


One option is to create your own overloaded new operator that can be implemented in terms of malloc.

This could be defined like:

enum MyNew {EMyNew};

void *operator new(size_t size, MyNew);

This can then be called by you as MyClass* myClass = new (EMyNew)MyClass;

Since this is implemented in terms of malloc, it should behave as expected. The only downer is that you will have to replace all the instances of where you have used new.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜