Avatar ·

В чем разница между статическими и динамическими (shared) библиотеками в C++?

Всем привет! Я недавно начал изучать C++ и пытаюсь разобраться с библиотеками. Смотрю на проекты на GitHub и вижу, что одни подключают .lib файлы, другие .dll (или .so в Linux). Насколько я понимаю, есть два типа библиотек: статические и динамические (shared). Кто-нибудь может объяснить простыми словами, в чем разница? У меня есть небольшой проект: я написал класс для работы с матрицами (умножение, транспонирование и т.д.). Сейчас я хочу сделать из него библиотеку, чтобы использовать в разных программах. Но не понимаю, какой тип выбрать. Что будет, если я использую статическую библиотеку? А если динамическую? Как это повлияет на размер исполняемого файла, скорость работы, удобство обновления? Вот пример кода, который я хочу превратить в библиотеку: ```cpp // matrix.h #pragma once #include class Matrix { public: Matrix(int rows, int cols); Matrix operator*(const Matrix& other) const; Matrix transpose() const; void print() const; private: int rows_, cols_; std::vector> data_; }; ``` И его реализация в matrix.cpp. Как мне правильно собрать это в библиотеку и потом использовать? Что выбрать для проекта, который будет использоваться другими разработчиками? Буду благодарен за подробное объяснение и примеры команд для компиляции. Заранее спасибо! <<>>

Основное различие: когда код попадает в вашу программу

Разница между статическими и динамическими (shared) библиотеками — это разница в моменте связывания кода с вашей программой. Статическая библиотека копирует код прямо в ваш исполняемый файл на этапе линковки. Динамическая библиотека остаётся отдельным файлом, и код загружается в память только при запуске программы.

Статические библиотеки (.lib в Windows, .a в Linux)

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

Плюсы:

  • Не нужно таскать с программой дополнительные файлы
  • Гарантированная версия библиотеки — никаких конфликтов DLL Hell
  • Немного быстрее на старте (не нужно загружать DLL)

Минусы:

  • Размер .exe больше (копия кода в каждом приложении)
  • Чтобы обновить библиотеку, нужно перекомпилировать всю программу
  • Несколько процессов не могут разделить один и тот же код в памяти

Динамические библиотеки (.dll в Windows, .so в Linux)

Динамическая библиотека — это отдельный файл, который подгружается во время выполнения. Код в ней может быть разделён между несколькими процессами (операционная система загружает .so/.dll в память один раз).

Плюсы:

  • Меньший размер .exe
  • Можно обновить библиотеку без перекомпиляции программы (заменить .dll/.so)
  • Экономия памяти, если несколько приложений используют одну библиотеку

Минусы:

  • "DLL Hell" — конфликты версий, когда программа требует старую DLL, а система подсовывает новую
  • Чуть медленнее запуск (загрузка и линковка в рантайме)
  • Нужно заботиться о том, чтобы библиотека была найдена (PATH, LD_LIBRARY_PATH)

Как собрать вашу матричную библиотеку

Статическая библиотека (Linux пример):

g++ -c matrix.cpp -o matrix.o          # компиляция
ar rcs libmatrix.a matrix.o             # создание статической библиотеки
g++ main.cpp -L. -lmatrix -o program    # линковка с программой

Динамическая библиотека (Linux пример):

g++ -fPIC -c matrix.cpp -o matrix.o     # -fPIC = Position Independent Code
g++ -shared -o libmatrix.so matrix.o    # создание shared library
g++ main.cpp -L. -lmatrix -o program    # линковка (запись имени .so в .exe)
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH  # чтобы программа нашла .so
./program

Для Windows с MinGW команды почти те же, только расширения .dll и .lib. С Visual Studio используйте проектные настройки.

Что выбрать для вашего проекта

Для библиотеки, которую будут использовать другие разработчики:

  • Если библиотека маленькая и редко меняется — статическая. Проще распространять: дали один .h и один .lib, и всё работает.
  • Если библиотека большая, часто обновляется или используется в нескольких программах — динамическая. Например, GUI-фреймворки (Qt, GTK), кодеки, графические движки.

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

<<>>

Дополнение: как работает линковка и компоновка

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

При динамической линковке символы разрешаются в момент запуска программы (или даже по запросу через dlopen/LoadLibrary). Это даёт интересные возможности:

  • Плагины — можно загружать библиотеки во время работы программы
  • Разделение данных — если библиотека использует разделяемую память, все процессы, загрузившие её, могут обмениваться данными

Ещё один нюанс: на Windows статическая библиотека (.lib) и "библиотека импорта" для DLL (тоже .lib) — это разные вещи. Не путайте их. Библиотека импорта — это просто заглушка, которая говорит линковщику: "этот символ будет в DLL, не ищи его сейчас".

Для вашего проекта с матрицами я бы посоветовал начать со статической библиотеки — это проще и надёжнее. Когда освоитесь, попробуйте сделать динамическую версию, чтобы понять разницу на практике.