Проблемы с компоновщиком C ++ - PullRequest
1 голос
/ 26 октября 2009

У меня есть это:

a.cpp

int localfunction () { return 1; }
int local_symbol = localfunction();

b.cpp

void thirdfunction () {};

main.cpp

void main () { thirdfunction (); }

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

Теперь в Visual C ++ и GCC я поместил a.cpp и b.cpp в статическую библиотеку (.lib). локальная функция больше не выполняется / не определена.

Из того, что я понимаю, символ определяется как "неиспользуемый" и удаляется. Но это звучит странно, потому что:

  • Почему он не удаляется, когда я не использую файл .lib?
  • Поскольку библиотека связана, почему компоновщик уничтожает код инициализации?

Я пытаюсь сделать так, чтобы в каждом используемом мной файле .lib был набор функций запуска, которые автоматически регистрируют некоторые данные. Основной исполняемый файл не должен знать, с какими файлами связаны ссылки, и не должен явно ссылаться на «локальную функцию» (/ INCLUDE работает, но это не оптимально)

Кстати: использование различных опций VC ++ (OPT: NOREF и т. Д.) Не решает проблему.

Спасибо! QbProg

Ответы [ 4 ]

3 голосов
/ 26 октября 2009

Статическая библиотека - это, по сути, библиотека или архив объектных файлов, скомпилированных из исходных файлов этой библиотеки.

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

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

О, а для максимальной переносимости main должен вернуть int.

1 голос
/ 26 октября 2009

При использовании gcc и необходимости запускаемой функции, которая запускается «автоматически» перед запуском main (), я бы просто использовал __attribute__((constructor)).

Возможно, есть аналогичный способ (прагма?) Для определения функции в VC ++, тогда вы могли бы использовать некоторые макропрепараты препроцессора, чтобы иметь общий способ объявления этих функций запуска.

0 голосов
/ 26 октября 2009

Вы должны помнить старые времена, когда размер был премиальным.

У вас есть обширная математическая библиотека с 10 000 различных функций. Теперь ваше приложение использует sin () и вы ссылаетесь на libm.a (или -lm).

Вы определенно не хотите использовать свое приложение с 9 999 функциями, которые вы не используете. Поэтому при использовании статических библиотек он извлекает из библиотеки только то, что используется (больше ничего).

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

0 голосов
/ 26 октября 2009

Ваш компоновщик примет меры для уменьшения размера исполняемого файла. Он определит, что ваш exe-файл не использует указанную функцию и не включит ее в окончательно сгенерированный код. Хотя это также зависит от того, какую оптимизацию вы используете в своем проекте.

Вместо этого, если вы хотите сделать это динамически, лучшей альтернативой является использование LoadLibrary и создание DLL, которую все ваши программы смогут загружать и динамически загружать функцию и регистрировать то, что вам нужно.

...