A colleague and I were having an interesting discussion about memory allocation when working with shared libraries and "where" code is actually executed.
Hint: I'm explicitly looking for answers in general terms. I know that the following points would work when using the exact same compiler and settings when building the shared library and application. I want to assume that the DLL is built using a completely different compiler than the application.
Given the following struct Foo
:
struct Foo
{
int m_FooBar = 1;
const char* GetBar()
{
return m_Bar.c_str();
}
void SetBar(const char* value)
{
m_Bar = value;
}
private:
std::string m_Bar;
};
Assuming the shared library exposes a function Foo* GetFoo()
and an external application calls it:
1.) What happens if the external application calls foo->SetBar("Hello")
?
Would SetBar
be executed inside the DLL and thus the memory allocation of m_Bar
be safe or would the memory allocation happen inside the external application and thus lead to issues?
2.) What happens if the external application copies the instance pointed to by the returned pointer?
Judging by the many posts out there warning against passing std::string
over DLL boundaries I assume that caused by potential different ABIs a default copy could cause problems. Is that correct?
3.) Would it be safe to define custom copy constructors and assignment operators that construct m_Bar
by calling .c_str()
on the passed instance so that those methods only rely on the API of std::string
and not on the ABI?
Hope some C++ gurus can answer some of these questions and shed some light on this topic.