Точка выполнения кода в C ++ и общих библиотеках - PullRequest
0 голосов
/ 30 января 2019

У нас с коллегой было интересное обсуждение распределения памяти при работе с общими библиотеками и "где" код фактически выполняется.

Подсказка: Я явно ищу ответыв общих чертах.Я знаю, что следующие пункты будут работать при использовании точно такого же компилятора и настроек при создании общей библиотеки и приложения.Я хочу предположить, что библиотека 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 ++ могут ответить на некоторые из этих вопросов и пролить свет на эту тему.

1 Ответ

0 голосов
/ 31 января 2019

1.) Что произойдет, если внешнее приложение вызовет foo-> SetBar («Hello»)?Будет ли SetBar выполняться внутри DLL, и, таким образом, выделение памяти m_Bar будет безопасным или выделение памяти будет происходить во внешнем приложении и, следовательно, приведет к проблемам?

Есть много проблем, не только в отношении памятивыделения или смешивание библиотек времени выполнения C.

Для начала Foo может даже не иметь одинаковый размер, std::string определение может быть совершенно другим и т. д. и т. д. и т. д.

2.) Что произойдет, если внешнее приложение скопирует экземпляр, на который указывает возвращенный указатель?Судя по многочисленным сообщениям, предупреждающим о пропуске std :: string через границы DLL, я предполагаю, что из-за потенциально различных ABI копия по умолчанию может вызвать проблемы.Это правильно?

Нет необходимости копировать, чтобы попасть в беду: поскольку вы ничего не знаете о памяти, на которую оно указывает, даже с использованием Foo, которым вы былиданный будет нарушать все.

3.) Было бы безопасно определить пользовательские конструкторы копирования и операторы присваивания, которые создают m_Bar, вызывая .c_str () для переданного экземпляра, чтобы эти методы полагались только наAPI для std :: string, а не для ABI?

Ваша общая идея попытаться перейти на самый низкий уровень - это хорошо.Однако пытаться играть с m_Bar - это не так.

Вместо этого предоставьте простой интерфейс C и, при необходимости, предоставьте классы-оболочки в заголовке.И даже в этом случае будьте осторожны при распределении / освобождении / использовании системных ресурсов, если вы связываетесь с различными библиотеками среды выполнения C (в Windows).

...