When working with windows dll's, it is established that we should limit the memory allocation/deallocation within the dll boundary since the dll could be using its own heap. So we have export allocators and free functions to from dll.
IsomeInterface* getObject();
void freeObject(IsomeInterface *object);
This way the object creation and deletion will reside within the dll.
Does this problem also exist on shared libraries on linux? When dealing with shared libs (.so) do we also need to take care of keeping allocation/deallocation within the shared lib. I did some quick tryout below and it works on linux. The same example would not work with windows dll (it will work with windows dll if both exe and dll compiled with /MD to make use of the same heap).
std::vector<int> vec;
vec.push_back(42);
PassAVector(vec);
where PassAVector
resides in a shared lib
void PassAVector(std::vector<int> &vec)
{
vec.push_back(1); // These would cause reallocation
vec.push_back(2);
vec.push_back(3);
vec.push_back(4);
vec.push_back(5);
}
Does this mean shared libs on unix share the heap with the executables (equivalent to the /MD switch on windows)?
Is it possible to compile (some compiler flags) the shared lib (.so) or the executable on linux in such a way that they start using different heaps (/MT switch on windows) and this problem surfaces?
EDIT: Found this which seem to suggest passing STL across boundaries is okay as long long as the compiler is gcc.
As long as you stick with Glibc or other "normal" allocators (jemalloc, tcmalloc, etc.) the heap state will be shared by all libraries and thus you'll be able to free memory allocated somewhere with malloc
anywhere you want.
In theory it may be possible to circumvent this. For example some library may be linked with custom implementation of malloc
/free
(via symbol scripts trickery of -Bsymbolic
) which has it's own private heap and thus will not interact well with other parts of your program. But I've never seen anything like this in real life.
STL containers are based on malloc
/free
so it is possible to pass/modify them across library boundaries as well. Of course different libraries may be compiled with different compilers and different incompatible versions of STL (e.g. libstdc++, libcxx, etc.) but their C++ container types would be different and compiler simply would not allow you to pass them across incompatible modules.
In C++ the normal way to change the heap is to overload the global operator new/delete.
In Windows that overload is restricted to the specific dll and thus you get the problems.
In Linux the overloaded global operator is normally truly global - so the first one wins, but if you really want specific heaps in them you can achieve that (and then you need the exported allocate and free-functions):
C++ custom global new/delete overriding system libraries
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