Although it seems to be a very common issue, I did not harvest much information: How can I create a safe interface between DLL boundaries regarding memory alloction?
It is quite well-known that
// in DLL a
DLLEXPORT MyObject* getObject() { return new MyObject(); }
// in DLL b
MyObject *o = getObject();
delete o;
might certainly lead to crashes. But since interactions like the one above are - as I dare say - not uncommon, there has to be a way to ensure safe memory allocation.
Of course, one could provide
// in DLL a
DLLEXPORT void deleteObject(MyObject* o) { delete o; }
but maybe there are better ways (e.g. smart_ptr?). I read about using custom allocators when dealing with STL containers as well.
So my inquiry is more about general pointers to articles and/or literature dealing with this topic. Are there special fallacies to look out for (exception handling?) and is this problem limited to only DLLs or are UNIX shared objects "inflicted" too?
The heap is an area of dynamically-allocated memory that is managed automatically by the operating system or the memory manager library. Memory on the heap is allocated, deallocated, and resized regularly during program execution, and this can lead to a problem called fragmentation.
Heap space is used for the dynamic memory allocation of Java objects and classes at runtime.
A function in the DLL allocates memory on the heap and passes a pointer to that memory to the exe.
“Heap” memory, also known as “dynamic” memory, is an alternative to local stack memory. Local memory is quite automatic. Local variables are allocated automatically when a function is called, and they are deallocated automatically when the function exits. Heap memory is different in every way.
As you suggested, you can use a boost::shared_ptr to handle that problem. In the constructor you can pass a custom cleanup function, which could be the deleteObject-Method of the dll that created the pointer. Example:
boost::shared_ptr< MyObject > Instance( getObject( ), deleteObject );
If you do not need a C-Interface for your dll, you can have getObject
return a shared_ptr.
Overload operator new
, operator delete
et. al for all your DLL classes and implement them within the DLL:
void* MyClass::operator new(size_t numb) {
return ::operator new(num_bytes);
}
void MyClass::operator delete(void* p) {
::operator delete(p);
}
...
This can easily be placed in a common base class for all classes exported by the DLL.
This way, allocation and deallocation are done entirely on the DLL heap. Honestly, I'm unsure whether it has any serious pitfalls or portability issues - but it works for me.
You may state that it "might certainly lead to crashes". Funny - "might" means the exact opposite of "certainly".
Now, the statement is mostly historical anyway. There is a very simple solution: Use 1 compiler, 1 compiler setting, and link against the DLL form of the CRT. (And you can probably get away skipping the latter)
There are no specific articles to link to, as this is a non-problem nowadays. You'd need the 1 compiler, 1 setting rule anyway. Simple things as sizeof(std::string)
depend on it, and you'd have massive ODR violations otherwise.
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