Копирует ли компоновщик содержимое функции или просто делает ссылку на нее? - PullRequest
0 голосов
/ 27 февраля 2019

Предположим, у меня есть код на языке C, и я собираю его на Linux-машине с gcc.

test.c:

#include <stdio.h>

int main() {
    printf("hi\n"); 
    return 0;
}

Я знаю, что stdio.h определяетprintf и тело printf существует в C library в двоичном формате.

Вот мои вопросы:

  1. При выполнении обычной компиляции с gcc test.c,компоновщик создает динамическую ссылку на printf или статическую ссылку?

  2. printf в конечном итоге выполняет системный вызов write().Копирует ли компоновщик C lib, определенный printf, в конечный исполняемый файл (который в итоге вызовет write () во время выполнения), или копирует write() непосредственно в конечный исполняемый файл.

или другими словами: если я открою исполняемый файл и переведу его в формат ascii, я увижу в нем «printf ()» или «write ()»?

Если я скомпилирую свой код и затем удалю C lib, мой код все еще будет работать?поскольку printf больше нигде не определен.

Ответы [ 2 ]

0 голосов
/ 27 февраля 2019

Сначала немного фона.В системах Unix (все, что я знаю) среда выполнения C содержит как стандартную реализацию функций C, так и так называемый код glue (требуется для вызова низкоуровневых функций ОС из программ на C).

В вашем примере printf() - это функция времени выполнения C, а write() - это клей интерфейс для write системного вызова.Предполагая, что мы говорим о linux, оба будут жить в библиотеке glibc.

Когда вы связываете вашу программу, по умолчанию компоновщик gcc сначала пытается динамически связать glibc (используя .so).Это можно изменить, используя аргумент -static для компоновщика - это вызовет статическое связывание glibc, более подробно можно найти здесь: Статическое связывание Glibc

Вы можете проверить конечный результатвведя ldd <path to your executable> - это покажет вам всю библиотеку .so, запрошенную компоновщиком.

0 голосов
/ 27 февраля 2019
  1. При обычной компиляции с gcc test.c компоновщик создает динамическую ссылку на printf или статическую ссылку?

Это зависит.Учитывая эту конкретную команду компиляции, если доступна динамическая версия библиотеки C, и если GCC создан для ее использования (обе из которых весьма вероятны), то GCC будет выполнять динамическое соединение.Если доступна только статическая версия библиотеки C, или если GCC построен или настроен для статической ссылки по умолчанию, будет выполняться статическая ссылка.

printf в конечном итоге совершает системный вызов write().Копирует ли компилятор C lib, определенный printf, в конечный исполняемый файл (который в итоге вызовет write() во время выполнения), или он копирует write() непосредственно в конечный исполняемый файл.

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

Если я скомпилирую свой код и затем удалю C lib, мой код все еще будет работать?поскольку printf больше нигде не определено.

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...