#c #static-linking #c-standard-library
#c #статическое связывание #c-standard-library
Вопрос:
У меня есть следующая программа:
# include <stdio.h>
int main(int argc, char *argv[]) {
printf("Hello World!n");
return 0;
}
Я скомпилировал ее (динамически связанную) и использовал ldd
дальше a.out
. Я видел:
linux-vdso.so.1
libc.so.6
ld-linux-x86-64.so.2
- Первый — это виртуальный общий объект, предоставляемый ядром.
- Вторая — стандартная библиотека на языке Си.
- Третий — динамический компоновщик.
Я не уверен, как статическое связывание влияет на первое и третье, и мне интересно, используется ли вся стандартная библиотека, даже если я включаю только один заголовок из нее.
Если я статически свяжу эту программу, будет ли результирующий двоичный файл
- содержать
linux-vdso.so.1
, даже если это предусмотрено ядром? - содержат всю стандартную библиотеку C, хотя я включил только
<stdio.h>
? - содержать
ld-linux-x86-64.so.2
, даже если он используется для запуска динамически связанных программ?
Комментарии:
1. stdio. h — это заголовочный файл, реализация зависит от компилятора, но если вы создадите статическую связанную библиотеку (я не уверен насчет других ОС / компиляторов) в компиляторе Visual Studio от Microsoft, весь MSVCRT (реализация стандартной библиотеки C от Microsoft) будет связан с двоичным файлом и значительноувеличивает размер двоичного файла.
2. Ни один из этих общих объектов не будет включен, если вы скомпилируете статический исполняемый файл. Однако это очень много
libc.a
(~ 20%), которые будут включены дословно. (не связано, поскольку это статическая, а не разделяемая библиотека). Просто скомпилируйте свою программу сcc -static
помощью, затем изучите ее сobjdump
помощью илиreadelf
;readelf -a | grep FILE
сообщит вам все объектные файлы изlibc.a
архива, которые были включены в ваш двоичный файл.3. Обратите внимание, что статические исполняемые файлы НА самом деле НЕ поддерживаются стандартной библиотекой GNU C (glibc; которую вы используете). Все развалится, и вы просто создадите своего рода «толстый» динамический исполняемый файл (статический исполняемый файл, который явно загружает общие объекты), как только вы используете какие-либо функции распознавания в своей программе. Компоновщик предупредит вас об этом.
4. Как сказал @UncleBilly, просто попробуйте, что вас останавливает? — В любом случае, при статическом связывании библиотеки компоновщик будет включать те объекты, которые необходимы для разрешения ссылки. Например, если вы просто вызываете
exit()
свою программу,printf()
она обычно не включается, даже если библиотека содержит ее. Все зависит от степени детализации объектов библиотеки. — И, если статическое связывание с компилятором Microsoft включает в себя так много, мне кажется, что это проблема этой библиотеки, а не общая проблема.