Зачем создавать файл .a из .o для статических ссылок? - PullRequest
21 голосов
/ 05 декабря 2009

Рассмотрим этот код:

one.c:

#include <stdio.h>

int one() {
   printf("one!\n");
   return 1;
}

two.c:

#include <stdio.h>

int two() {
   printf("two!\n");
   return 2;
}

prog.c

#include <stdio.h>

int one();
int two();

int main(int argc, char *argv[]) 
{
   one();
   two();

   return 0;
}

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

gcc -c -o one.o one.c
gcc -c -o two.o two.c
gcc -o a.out prog.c one.o two.o

Это прекрасно работает.

Или я мог бы создать статическую библиотеку:

ar rcs libone.a one.o
ar rcs libtwo.a two.o
gcc prog.c libone.a libtwo.a
gcc -L. prog.c -lone -ltwo

Итак, мой вопрос: зачем мне использовать вторую версию - ту, в которой я создал файлы ".a", а не связывать мои файлы ".o"? Они оба кажутся статически связывающими, так есть ли преимущество или архитектурное различие в одном против другого?

Ответы [ 6 ]

41 голосов
/ 05 декабря 2009

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

В вашем примере нет никакого преимущества, но вы могли бы сделать:

ar rcs liboneandtwo.a one.o two.o

Тогда связывание вашей программы становится проще:

gcc -L. prog.c -loneandtwo

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

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

12 голосов
/ 05 декабря 2009

Разница будет в размере исполняемого файла, хотя, возможно, не для вашего примера.

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

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

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

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

2 голосов
/ 05 декабря 2009

Вы можете поместить коллекцию файлов в файл архива (.a) для последующего повторного использования. Стандартная библиотека - хороший пример.

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

2 голосов
/ 05 декабря 2009

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

Кстати, абсолютно бессмысленно создавать файл .a, содержащий только один файл .o.

1 голос
/ 05 декабря 2009

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

0 голосов
/ 15 декабря 2009

Всякий раз, когда мне задают этот вопрос (освежители в моей команде), «почему (или иногда даже« что есть ») .a?», Я использую ответ ниже, который использует .zip в качестве аналогии.

"dotAy подобен zip-файлу всех dotOh, которые вы хотели бы связать при сборке exe / lib. Экономия дискового пространства, плюс не нужно вводить имена всех задействованных dotOh."

пока, кажется, это заставило их понять. ;)

...