2015-07-03 3 views
2

У меня есть следующие настройки:Статическая библиотека связаны два раза

  1. Статическая библиотека
  2. Динамическая библиотека, которая связывается с (1)
  3. исполняемый файл, который связывает с (1.) и (2.)

Код из статической библиотеки теперь дублируется и присутствует в динамической библиотеке и исполняемом файле.

Вопросы:

это данные (глобальные переменные, статические члены класса) также дублируется и не исполняемый файл и длл увидеть одни и те же данные?

Есть ли разница между Linux и Windows?

Как бы вы это разрешили?

Edit:

Спасибо за ответы, я могу не объяснить, что произошло в моем случае точно.

В статической библиотеке не было флажков экспорта/импорта. Динамическая библиотека шляпу экспорта на свои собственные символы.

Окна:

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

Linux:

Динамическая библиотека была копия segement текстовых данных статической библиотеки. Динамическая библиотека, хотя и включала все символы (текст и данные) из статической библиотеки в свою собственную таблицу символов. -> Исполняемый файл видит, что динамическая библиотека уже определила все символы статической библиотеки и не переопределяет их.

Это плохо, потому что вы, как правило, хотите иметь такое же поведение в Linux и на окнах.

  1. Share символы (по умолчанию на Linux)

    • Добавить команду DLL экспорта всех символов из статической библиотеки при связывании его к общей библиотеке. __attribute__ ((dllexport))
    • Добавить команду импорта dll при связывании статической библиотеки с исполняемым файлом.__attribute__ ((dllimport))
    • код и данные хранятся только в общей библиотеке и связываемый от внешнего
  2. Reduntant символов (по умолчанию на окнах)

    • Вы должны убедиться, что символы статическая библиотека не включена в таблицу символов разделяемой библиотеки
    • __attribute__ ((visibility ("hidden"))) по gcc
    • При связывании исполняемого файла символы из статического li Брары не могут быть найдены нигде, поэтому они снова включены.
+1

Да, данные дублируются. Вы решили бы его с помощью динамической библиотеки. – UmNyobe

+0

@UmNyobe: есть уже DLL; создание другого не помогло бы, поскольку оно не будет передавать глобальные данные с первого. –

+0

Являются ли библиотеки предварительно скомпилированными или доступными в качестве исходного кода? –

ответ

4

Насколько я знаю, это зависит от операционной системы (потому что язык C++ ничего не говорит о том, как библиотеки должны работать).

На окнах, вы получите в два раза код и данные, и хуже того, что все дважды глобальные переменные, объявленные в этой библиотеке (!)

Эта проблема проявляется при связывании статически стандартной библиотеки в программа и библиотека, использующие это, когда вы получаете два распределителя по умолчанию, и если вы вызываете new в библиотеке и delete - с другой стороны, объект будет протекать на стороне new, и куча, скорее всего, будет повреждена на стороне delete.

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

+0

+1 для нового трюка: у меня это было в прошлом, и я быстро научился избегать использования гетерогенных сборок. –

+0

Если все вызовы библиотеки _functional_ (то есть они не наблюдают и не изменяют какой-либо глобальный статус), нормально использовать статическое связывание, потому что код может быть более эффективным/малым (включены только символы, которые вы используете), во всех остальных случаях я предлагаю против него – pqnet

+0

Кажется, что на Linux как-то данные не копируются. http://stackoverflow.com/questions/4925233/global-variable-has-multiple-copies-on-windows-and-a-single-on-linux-when-compil – dari

0

ИМО это неприятная ситуация, так как есть два выполняемых файлы (EXE и DLL), каждый со своим экземпляром кода и глобальных данных. Они построены независимо и не могут передавать свои карты памяти.

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

+0

Я правильно понял ваш ответ: повторно объявите все переменные и функции из статической библиотеки в dll, чтобы исполняемый файл не связывался со статической библиотекой. – dari

+0

Да, это то, что я имею в виду, надеясь, что компоновщик согласится. Заголовок библиотеки будет существовать в трех версиях: стандартный для компиляции статики, экспорт для сборки dll и импорт для exe. –

Смежные вопросы