Почему символы общей библиотеки не разрешаются во время ссылки?

Это мой второй пост на этом сайте, в котором я пытаюсь понять процесс компиляции / компоновки с помощью gcc. Когда я пытаюсь создать исполняемый файл, символы должны быть разрешены во время компоновки, но когда я пытаюсь создать общую библиотеку, символы не разрешаются во время компоновки этой библиотеки. Возможно, они будут решены, когда я попытаюсь создать исполняемый файл с использованием этой общей библиотеки. Руки вверх:

bash$ cat printhello.c
#include <stdio.h>
//#include "look.h"

void PrintHello()
{
look();
printf("Hello World\n");
}

bash$ cat printbye.c
#include <stdio.h>
//#include "look.h"

void PrintBye()
{
look();
printf("Bye bye\n");
}

bash$  cat look.h
void look();

bash$ cat look.c
#include <stdio.h>

void look()
{
printf("Looking\n");
}

bash$ gcc printhello.c printbye.c
/usr/lib/gcc/i386-redhat-linux/4.1.2/../../../crt1.o: In function `_start':
(.text+0x18): undefined reference to `main'
/tmp/cck21S0u.o: In function `PrintHello':
printhello.c:(.text+0x7): undefined reference to `look'
/tmp/ccNWbCnd.o: In function `PrintBye':
printbye.c:(.text+0x7): undefined reference to `look'
collect2: ld returned 1 exit status

bash$ gcc -Wall -shared -o libgreet printhello.c printbye.c
printhello.c: In function 'PrintHello':
printhello.c:6: warning: implicit declaration of function 'look'
printbye.c: In function 'PrintBye':
printbye.c:5: warning: implicit declaration of function 'look'

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

Спасибо джаграти

6 ответов

Решение

Делает добавление -z defs при сборке библиотеки делай что хочешь? Если нет, проверьте справочные страницы ld, есть довольно много вариантов обработки неопределенных символов.

Поскольку вы не указали опцию -c (только для компиляции), вы попросили gcc скомпилировать два исходных файла и связать их со стандартной библиотекой (libc) и запуском во время выполнения c (обычно crt0), чтобы создать работающий файл. программа. crt0 пытается войти в вашу программу, вызывая main(), который является неопределенным символом, который компоновщик не может найти. Он не может найти его, потому что у вас нет main () ни в одном из ваших файлов.c, верно?

Итак, к вашему актуальному вопросу: "Почему символы общей библиотеки не разрешаются во время ссылки?" Ответ таков: что вы подразумеваете под "временем ссылки"? По определению, динамически связанная программа не "связана", пока не запустится (или, может быть, даже тогда, в зависимости от вашей системы).

В системе Linux вы можете увидеть, от каких динамических библиотек зависит программа, с помощью команды ldd (в Mac OS используйте 'otool -L'). Вывод ldd скажет вам, от каких динамических библиотек зависит программа, какие были найдены в пути поиска библиотек, а какие нет (если таковые имеются).

Когда ваша динамическая программа запускается, динамический компоновщик, который был связан с ней, находит и загружает динамические библиотеки, от которых зависит программа, и "исправляет" ссылки на внешние символы. Если что-то из этого не получится, ваша программа не запустится. Один из всех ранее неразрешенных символов был разрешен, динамический компоновщик возвращается, и среда выполнения C вызовет вашу функцию main (). (Это несколько отличается в Mac OS, но похоже, что связывание происходит после запуска вашей программы.)

Я думаю, что вариант компоновщика -Bsymbolic это то, что вы ищете.

Исполняемый файл требует точки входа. Но разделяемая библиотека может быть построена без точки входа, и позже исполняемый файл может быть скомпилирован с этой разделяемой библиотекой.

Связанный не может знать, по крайней мере, в ELF, где находятся символы (т.е. в каких библиотеках). В OS X, с другой стороны, вам нужно связывать библиотеки так, как вы описали. В конце концов, это вопрос дизайна. Один более гибкий, другой более строгий.

Даже когда вы создаете разделяемую библиотеку, она должна разрешать все зависимости.

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

1) Создайте разделяемую (look.) библиотеку с помощью look ()
2) Создайте разделяемую (hg.) библиотеку с помощью ссылки hello () bye () для look.
3) Создайте приложение с помощью main (), который ссылается на hg.

Во время выполнения приложение будет загружать hg., который будет загружать внешний вид совместно используемой библиотеки.

Другие вопросы по тегам