I'm experimenting with shared libraries to build a modularized program.
There are two cpp files to compile:
Shared library, compile with
g++ -fPIC -shared module.cpp -o module.so
//module.cpp
#include <iostream>
File using the shared library, compile with
g++ src/main.cpp -ldl -o binary
or
g++ -DFIX src/main.cpp -ldl -o binary
//main.cpp
#include <dlfcn.h>
#ifdef FIX
# include <iostream>
#endif
int main()
{
void* h = dlopen("./module.so", RTLD_LAZY);
if ( h )
{
dlclose(h);
}
}
With FIX
undefined, valgrind reports lot's of still reachable memory (5,373bytes), with FIX
defined, no memory is leaked.
What's the problem with using iostream
in shared libraries?
This problem occurs with g++-4.6, g++-4.7 and g++-4.8. g++-4.4 does not show this behaviour. I don't have other compilers to test with, sadly (and I don't want to switch to g++-4.4 because of this).
Update:
Compiling the shared library file with the additional flags -static-libstdc++ -static-libgcc
reduces the number of leaked blocks, but not completely. -static-libgcc
alone has no effect, -static-libstdc++
has some effect, but not as much as both.
1. Why or how does this code snippet "fix" the issue?
I'm not sure why without digging into the libstdc++ code, but I assume that the memory allocated by the iostreams library, which is kept allocated for the duration of the whole program, is reported as a problem by valgrind when it is allocated in a shared library, but not when allocated in the main program.
2. What equivalent, independent (from the standard library) code snippet provides the same bug fix?
Firstly, I don't know why you want something "independent from the standard library" when the still reachable memory is probably being allocated by the standard library. The fix is either don't use the standard library at all, anywhere, or use it differently.
Secondly, that "fix" is undefined behaviour, because you violate the One Definition Rule by redefining std::ios_base
differently to the proper definition in the std lib.
The correct way to get the same behaviour is to #include <iostream>
in your main.cpp
file, including <iostream>
defines a static std::ios_base::Init
object. Alternatively, just #include <ios>
and then define the static
variable (but don't redefine the std::ios_base
type) but that's basically what <iostream>
does, so you might as well use that.
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