Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Memory / heap management across DLLs

Tags:

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?

like image 978
mats Avatar asked Feb 15 '10 13:02

mats


People also ask

How is memory heap managed?

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.

Can heap be used for dynamic memory allocation?

Heap space is used for the dynamic memory allocation of Java objects and classes at runtime.

Can a DLL allocate memory?

A function in the DLL allocates memory on the heap and passes a pointer to that memory to the exe.

What is heap dynamic memory allocation?

“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.


3 Answers

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.

like image 185
Björn Pollex Avatar answered Oct 04 '22 20:10

Björn Pollex


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.

like image 25
Alexander Gessler Avatar answered Oct 04 '22 20:10

Alexander Gessler


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.

like image 39
MSalters Avatar answered Oct 04 '22 22:10

MSalters