Почему символы общей библиотеки не разрешаются во время ссылки? - PullRequest
8 голосов
/ 01 июля 2010

Это мой второй пост на этом сайте, в котором я попытался понять процесс компиляции / компоновки с помощью 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 ]

7 голосов
/ 01 июля 2010

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

4 голосов
/ 26 сентября 2012

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

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

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

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

2 голосов
/ 03 июля 2010

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

0 голосов
/ 08 июля 2010

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

0 голосов
/ 01 июля 2010

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

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

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

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

0 голосов
/ 01 июля 2010

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

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