Как работает статическая библиотека C?

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


Например, у нас есть два файла:

/*main.c*/
int main (int argc, char* argv[]){
    fc(1); /*This function is defined in fc.c*/
}

Другой файл:

/*fc.c*/
int fc(int x){
    return fe(x);
}
int fe(int y){
    return y + 1;
}

Собираем fc.c:

gcc -c fc.c

Тогда мы получаем fc.o.

Теперь давайте создадим библиотеку с именем test:

ar rcs libtest.a fc.o

Теперь у нас есть libtest.a.

Теперь компилируем main.c

gcc -c main.c

И получаем main.o

Давайте свяжем наш main.o с нашим libtest.a

гкк-л. main.o -ltest

Получаем искомый a.out

Проверка его символов:

нм a.out

Между всеми символами мы находим:

080483cc T fc
080483df T fe

Выглядит неплохо. НО!

Если наш main.c изменится для этого?

/*main.c*/
int main (int argc, char* argv[]){
    fe(1); /*This function is defined in fc.c*/
}

После компиляции main.c и привязки нового main.o к нашей библиотеке я все равно найду символ для fc. Но мне этот код не нужен.

Вопросы

-Разве библиотека не должна "давать мне" только тот код, который мне нужен в main.c?
-Должны ли функции быть в отдельных модулях перед добавлением в библиотеку?
-Что, если бы у меня было 300 функций ? Нужно ли мне делать 300 модулей?


person n233g16    schedule 06.01.2016    source источник
comment
Зачем вам 300 модулей? Вы можете иметь 300 функций в одном.   -  person Iharob Al Asimi    schedule 06.01.2016
comment
@ iharob, потому что, если все они находятся в отдельных модулях, связывание программы с библиотекой загрузит только те функции, на которые ссылается программа (и рекурсивно). Если они все находятся в одном модуле, при компоновке будут загружены все 300 функций, даже если программа вызывает только одну функцию в библиотеке.   -  person FredK    schedule 06.01.2016
comment
Возможный дубликат stackoverflow.com/questions/6687630/   -  person kfx    schedule 06.01.2016


Ответы (2)


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

person FredK    schedule 06.01.2016
comment
спасибо за краткий ответ. Итак, чтобы иметь независимость между функциями, я должен сделать модуль для каждой функции, и внутри этого модуля должны быть только функции, необходимые для работы основной функции, верно? - person n233g16; 06.01.2016
comment
да, если какая-то другая функция также не нуждается в дополнительных функциях для работы. В этом случае дополнительные функции также должны быть в отдельном модуле. - person FredK; 06.01.2016
comment
И принцип остается, поэтому используется только код этих лишних функций, а не целый бесполезный модуль. Большое спасибо за помощь! - person n233g16; 06.01.2016

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

GCC может сделать эту "сборку мусора" неиспользуемых функций, если добавить эти флаги:

  1. -ffunction-sections в качестве флага времени компиляции. Он указывает компилятору создать отдельный раздел (см. формат объектного файла). ) для каждой функции. Также есть флаг -fdata-sections с аналогичным значением, который работает для переменных.

  2. -Wl,--gc-sections в качестве флага времени компоновки. Часть -Wl указывает GCC передать компоновщику следующие параметры. --gc-sections означает "мусорные разделы выбора, из которых весь код удален". Поскольку из-за опций времени компиляции каждая функция имеет отдельный раздел, она эффективно выполняет сокращение на уровне функций.

person kfx    schedule 06.01.2016
comment
С учетом сказанного, я мог бы поместить функции fc и fe в один модуль? Тогда компоновщик удалит неиспользуемые функции? - person n233g16; 06.01.2016
comment
Что именно вы подразумеваете под модулем? Если функции находятся в разных библиотеках, конечно, их можно выбросить отдельно. Если нет, то должна применяться методика, описанная выше (насколько мне известно). - person kfx; 06.01.2016
comment
Под модулем я подразумеваю файл .c. - person n233g16; 06.01.2016
comment
Да, если разные файлы .c скомпилированы в разные файлы .o, они по умолчанию отбрасываются отдельно. - person kfx; 06.01.2016