2011-10-09 1 views
0

У меня создается впечатление, что по целому ряду причин небезопасно передавать стандартные объекты библиотеки (в частности, шаблонные) между модулями, когда они могут быть скомпилированы с различными версиями стандартной библиотеки или разных компиляторов. Моя цель теперь - найти жизнеспособное решение для этого, особенно в случае общих указателей и строк.Альтернативы передаче объектов между модулями

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

  • C и другие примитивные типы, которые никогда не меняются (не представляется возможным, поскольку требуются более сложные типы)
  • Виды из стандартизированной библиотеки, либо:
    • Пользовательский вариант (который требует добавления строки и таких классов, что, честно говоря, звучит ужасно)
    • Некоторая внешняя библиотека, которая уже предоставляет такие вещи (первая мысль - это Boost, но даже без раздувания т включает в себя, он кажется слишком шаблонами тяжело работать)
  • Некоторое магическое обстоятельство фактически делает его безопасным (во всех случаях, но shared_ptr)

Реальная проблема, как представляется, такие вещи, как общие указатели, которые сильно зависят от шаблонов.

Вопрос о том, было ли задание пропущенных стандартных объектов библиотеки задано много раз, и в некоторых случаях всегда возвращается к тому, чтобы быть плохим веществом, но фактическое решение, которое не требует написания тонны кода, который уже сделан в десятки раз кажется редким.

Есть ли решение для этого, которое не связано с внедрением внутреннего подсчета ссылок и пользовательских строк, или это просто цена, которая должна быть заплачена за перекрестную версию/безопасность компилятора/платформы?

+2

Что такое «модуль»? –

+0

@CatPlusPlus Для проекта я сейчас работаю, прежде всего EXE/DLL/HDR (Win32 PE). Но проблема существует для всех, включая ELF PE, SO, DYLIB и т. Д. (Надеюсь, решение тоже). – ssube

+0

Стандартная библиотека STL или C++? –

ответ

2

Нет решения, помимо разбивки классов на их тривиальные типы элементов и передачи их по отдельности, если вы используете разные компиляторы для компиляции ваших модулей. Если вы используете один и тот же компилятор и только разные его версии, вполне возможно, что модули уже совместимы (если только ABI не изменился, например, в классе и т. Д.). Кроме того, ABI стандартных типов библиотек C++ может быть изменен, в этом случае вы можете обходить его, используя вместо него стороннюю библиотеку, которая обеспечивает те же функции, но гарантирует совместимость с двоичными файлами (например, Qt делает это). Но это не идеальное решение, так как библиотека, используемая вашей основной программой, должна быть более новой, чем версия библиотеки, связанная всеми модулями.Но этого часто бывает достаточно, потому что чаще всего вам нужны только те старые плагины, которые продолжают работать с новой версией вашей программы, а не то, что новые плагины работают со старой версией вашей программы.

+0

Если я правильно понимаю, вы, по сути, говорите, что нет простого или простого решения, и лучше всего использовать реализации всех необходимых классов из известной и постоянной библиотеки? – ssube

0

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

Я думаю, что вы можете передавать объекты по модулю (модулями Я имею в виду библиотеки DLL + основные EXE) границы , проблема заключается только в том, что нельзя использовать распределение кучи и статические переменные.

Итак, если вы проходите только структуру, предназначенную для чтения, все должно быть хорошо.

Но как только вы начнете выделять, резервировать и т. Д. И т. Д. Вещи разрываются (разные кучи, без статики).

Можете ошибаться, поэтому, пожалуйста, не пропустите голосов.

+0

Сообщество SO достаточно велико, что вам не нужно отправлять ответ, если вы не уверены. Есть больше проблем с передачей 'std ::' объектов между модулями (например, несовпадающими реализациями). – tenfour

+2

Извините; если ваш пост неправильный, он будет занижен! Просить прощения не имеет значения. :) –

+0

К сожалению, я не могу предположить тот же компилятор, и версии почти наверняка будут развернуты из разных версий. Также объект не доступен для чтения (общие указатели являются одним из больших). – ssube

0

Проблема заключается не в передаче объектов между различными модулями, это работает просто отлично. То, что вам нужно обеспечить, - это то, что объекты, созданные модулем X, всегда удаляются модулем X.

Вы можете сделать эту работу, если вы предоставляете функции-обертки для любых операций, требующих выделения/освобождения памяти, чтобы вы имели контроль над тем, какой модуль выполняет эти функции.

Например, это класс заголовок класса, который является безопасной памяти:

class SomeObj { 
private: // private ctor/dtor to prevent outsiders from using them 
    SomeObj() {} 
    virtual ~SomeObj() {} 
public: 
    static SomeObj* create(); 
    void destroy(); 
}; 

А вот реализация:

SomeObj* SomeObj::create() 
{ 
    return new SomeObj(); 
} 

void SomeObj::destroy() 
{ 
    delete this; 
} 

С установкой класса таким образом вы заставляете любой, кто создает или разрушает объект, пройти через create() и destroy(), поэтому модуль, который имеет эти функции, всегда будет управлять памятью для этого класса. Обратите внимание, что create() и destroy() не могут быть встроены.

Для более сложных классов, таких как контейнеры STL, это становится немного сложнее, так как вам нужно будет обернуть больше функций, кроме создания и уничтожения, но это можно сделать.

+0

Я понимаю, что распределение является особенно плохой проблемой, но я слышал, что шаблонные типы могут нарушать одно правило определения при переходе между модулями. Я знаю, что могу обернуть их все, но это единственное решение (обертывание таких вещей, как std :: string - это боль). – ssube

+0

Если у вас есть только одна версия STL, используемая во всех ваших модулях, и все модули скомпилированы с одинаковыми настройками (упаковка, модель памяти и т. Д.), Вы должны иметь возможность перемещать строки и другие объекты STL через модули. Техника обертывания, о которой я говорил, будет необходима только для методов, которые выделяют или освобождают память. Если вы придерживаетесь доступа только для чтения на внешних модулях, вы должны быть в порядке. – Miguel

+0

У компилятора нет гарантий, а тем более настроек или версии. Только для чтения из других модулей просто невозможно. – ssube