What happens if two libraries (dynamicaly linked) have their own globally overridden version of the new and the delete operators and they use their own memory management?
Is it generally wrong to ship memory management facilities inside a library, or can it be good in some cases to provide memory management only for some specific classes, defining only class-specific new and delete operators override?
Are there some differences in the case of static linked libraries?
New and Delete operators can be overloaded globally or they can be overloaded for specific classes. If these operators are overloaded using member function for a class, it means that these operators are overloaded only for that specific class.
Memory that is dynamically allocated using the new operator can be freed using the delete operator. The delete operator calls the operator delete function, which frees memory back to the available pool. Using the delete operator also causes the class destructor (if one exists) to be called.
The main difference between new and delete operator in C++ is that new is used to allocate memory for an object or an array while, delete is used to deallocate the memory allocated using the new operator. There are two types of memory as static and dynamic memory.
Examples: delete p; delete q; To free the dynamically allocated array pointed by pointer-variable, use the following form of delete: // Release block of memory // pointed by pointer-variable delete[] pointer-variable; Example: // It will free the entire array // pointed by p.
In general, this is labelled "here be dragons". It depends on all sorts of things. Often the two libraries will fight, and new and delete will end up overridden by one of them - that's the best you can hope for.
Alternatives:
Library A starts up. Overrides new/delete, allocates some memory. Library B starts up and overrides. At system shutdown, library A's memory is freed with library B's delete. That is not good.
Memory allocated in library A uses library A's override, and similarly for library B. If you ever end up with memory allocated in library A being freed by library B, you will lose. (And it can be even more confusing, because if the object being deleted by B has a virtual destructor, the deletion can end up being done by A ... so it works.)
I think Martin pretty well answers your question, by outlining what happens and also nothing that it's a bit dangerous and not highly advisable (there be dragons indeed). Let me extend it a bit by providing an alternative: avoid overriding new/delete, and instead use the allocator concept.
For instance, if you look at std::vector, you notice that it is templated both on what type it stores, but also on an allocator. By writing a conforming allocator, you can control exactly how std::vector allocates and de-allocates memory. Notice how nice and loosely coupled this is: you have no difficulty exerting full control over memory allocation even though you can't change any of the original std::vector source code.
If you want library B to do allocation in a specific way, what I would do is:
To clarify step 3, what I mean is write something like this in a fundamental header file of your library:
template <class T>
using my_lib::vector = std::vector<T, my_lib::MyAllocator<T>>;
Now you can use ''vector'' anywhere in your library, which will be a normal vector but using your allocation scheme.
Step 1 can range from very easy (for stateless allocators) to quite tricky (there's a number of gotcha with stateful allocators). As for step 2, it's quite straightforward as far as dynamic memory for containers goes as all of the containers in the standard library already support this. But if you are using dynamic memory for e.g. polymorphism, you'll need to do a bit of extra work (probably write a suitable wrapper) to do this in an allocator-aware way.
If someone has good examples of reasons why you'd want to override new/delete as opposed to using allocators (e.g. because there is something you can't do with allocators) I'd be interested to hear them.
Edit: and just to bring this full circle, note that there will not be any problem using libraries A and B simultaneously if you do this, as no global operators have been overridden.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With