Различия между версиями 1 и 2
Версия 1 от 2017-01-27 22:26:02
Размер: 4512
Редактор: FrBrGeorge
Комментарий:
Версия 2 от 2017-01-27 22:56:09
Размер: 5202
Редактор: FrBrGeorge
Комментарий:
Удаления помечены так. Добавления помечены так.
Строка 7: Строка 7:
 {{{#!highlight c {{{#!highlight c
Строка 17: Строка 17:
  Здесь мы определяем переменную `var` и функцию `main`, а функции `printf` и `scanf` становятся доступны только в процессе компоновки. С помощью ключа `-c` остановим процесс трансляции на объектном файле (файл этот будет называться `simple.o`): Здесь мы определяем переменную `var` и функцию `main`, а функции `printf` и `scanf` становятся доступны только в процессе компоновки. С помощью ключа `-c` остановим процесс трансляции на объектном файле (файл этот будет называться `simple.o`):
Строка 39: Строка 39:
$ nm simple.static | egrep ' (main|var|printf|scanf)$'
000000000040096e T main
0000000000407440 T printf
0000000000407570 T scanf
00000000006b2d58 B var
Строка 44: Строка 49:
Статическая компоновка добавляет в объектный файл ''всю'' исполняющую систему Си и всю отладочную информацию к ней, так что получается программа в 1000 (!) раз больше. Отладочную информацию можно удалить: Статическая компоновка добавляет в объектный файл ''всю'' исполняющую систему Си и всю отладочную информацию к ней, так что получается программа в 1000 (!) раз больше. С помощью `egrep` из отладочной информации добудем сведения о четфрёх именах. Они уже определены, и даже адреса есть.

Отладочную информацию можно удалить:
Строка 55: Строка 62:
$ cc simple.o -o simple.dynamic
$ nm simple.dynamic
<printf и scanf в этом варианте нет>
$ ldd
{{{
$ cc -std=c89 simple.c -o simple.dynamic
$ nm simple.dynamic | egrep ' (main|var|printf|scanf)'
0000000000400566 T main
                 U printf@@GLIBC_2.2.5
                 U scanf@@GLIBC_2.2.5
0000000000601038 B var
$ ldd simple.dynamic
        linux-vdso.so.1 (0x00007ffe939de000)
        libc.so.6 => /lib64/libc.so.6 (0x00007fefe7726000)
        /lib64/ld-linux-x86-64.so.2 (0x000055e6bc426000)

}}}

Математическая библиотека

  • Повторение: создание исполняемой программы из исходного кода на Си:

    1. Трансляция: файл на Си → объектный файл (все операторы Си переведены на машинный язык)
    2. Компоновка: объектный файл → исполняемый файл (к объектному файлу добавлена исполняющая подсистема Си и другие подпрограммы, непосредственно либо в виде указания библиотеки, откуда эти подпрограммы может загрузить операционная система)

Пример: файл simple.c

   1 #include <stdio.h>
   2 
   3 int var;
   4 
   5 void main() {
   6     scanf("%d", &var);
   7     printf("%d\n", var);
   8 }

Здесь мы определяем переменную var и функцию main, а функции printf и scanf становятся доступны только в процессе компоновки. С помощью ключа -c остановим процесс трансляции на объектном файле (файл этот будет называться simple.o):

$ cc -std=c89 simple.c -c -o simple.o
$ hexdump -C simple.o
<содержмое объектного файла в шестнадцатеричном виде>
...
$ nm simple.o        
0000000000000000 T main
                 U printf
                 U scanf
0000000000000004 C var
$ ls -l simple.*
-rw-r--r-- 1 george george   94 янв 27 21:32 simple.c
-rw-r--r-- 1 george george 3488 янв 27 21:42 simple.o

Утилита hexdump покажет нам внутренности simple.o (среди трёхкилобайтного шестнадцатеричного месива можно отыскать все четыре названия). Утилита nm — выдаст информацию о том, какие идентификаторы используются в программе, при этом те, что не определены, помечены как U (undefined). При компиляции использовался старый стандарт c89, чтобы функции назывались более наглядно.

Компоновка:

$ cc -static simple.o -o simple.static
$ nm simple.static
<множество имён, среди которых есть уже `main, printf, scanf и var>
$ nm simple.static | egrep ' (main|var|printf|scanf)$'
000000000040096e T main
0000000000407440 T printf
0000000000407570 T scanf
00000000006b2d58 B var
$ ls -l simple.*                          
-rw-r--r-- 1 george george      94 янв 27 21:32 simple.c
-rw-r--r-- 1 george george    3488 янв 27 22:17 simple.o
-rwxr-xr-x 1 george george 3487080 янв 27 22:17 simple.static

Статическая компоновка добавляет в объектный файл всю исполняющую систему Си и всю отладочную информацию к ней, так что получается программа в 1000 (!) раз больше. С помощью egrep из отладочной информации добудем сведения о четфрёх именах. Они уже определены, и даже адреса есть.

Отладочную информацию можно удалить:

$ strip simple.o simple.static 
$ ls -l simple.*              
-rw-r--r-- 1 george george     94 янв 27 21:32 simple.c
-rw-r--r-- 1 george george    880 янв 27 22:21 simple.o
-rwxr-xr-x 1 george george 730112 янв 27 22:21 simple.static

Размер раз в 5 меньше.

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

$ cc -std=c89 simple.c -o simple.dynamic               
$ nm simple.dynamic | egrep ' (main|var|printf|scanf)' 
0000000000400566 T main
                 U printf@@GLIBC_2.2.5
                 U scanf@@GLIBC_2.2.5
0000000000601038 B var
$ ldd simple.dynamic 
        linux-vdso.so.1 (0x00007ffe939de000)
        libc.so.6 => /lib64/libc.so.6 (0x00007fefe7726000)
        /lib64/ld-linux-x86-64.so.2 (0x000055e6bc426000)

Домашнее задание

  1. {i} Прочитать что-нибудь из учебника

  2. Сделать что-нибудь из задачника

  3. …или из другого задачника

  4. <!> Задание повышенной хитрости


FrBrGeorge/LinkingC (последним исправлял пользователь FrBrGeorge 2023-09-26 15:13:09)