У нас с коллегой было интересное обсуждение распределения памяти при работе с общими библиотеками и "где" код фактически выполняется.
Подсказка: Я явно ищу ответыв общих чертах.Я знаю, что следующие пункты будут работать при использовании точно такого же компилятора и настроек при создании общей библиотеки и приложения.Я хочу предположить, что библиотека DLL построена с использованием совершенно другого компилятора, чем приложение.
Учитывая следующее 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;
};
Предполагая, что совместно используемая библиотека предоставляет функцию Foo* GetFoo()
и внешнее приложение вызывает его:
1.) Что произойдет, если внешнее приложение вызовет foo->SetBar("Hello")
?
Будет ли SetBar
выполняться внутри DLL, и, таким образом, выделение памяти m_Bar
будет безопасным или будетВыделение памяти происходит внутри внешнего приложения и, таким образом, приводит к проблемам?
2.) Что произойдет, если внешнее приложение скопирует экземпляр, на который указывает возвращенный указатель?
Судя по многочисленным публикациям, предупреждающим о прохождении std::string
за границами DLL Я предполагаю, что из-за возможных различных ABI копия по умолчанию может вызвать проблемы.Это правильно?
3.) Было бы безопасно определять пользовательские конструкторы копирования и операторы присваивания, которые создают m_Bar
, вызывая .c_str()
в переданном экземпляре, чтобы эти методы полагались только на API std::string
ине на ABI?
Надеюсь, некоторые гуру C ++ могут ответить на некоторые из этих вопросов и пролить свет на эту тему.