Александру Талееву о проблемах с VS |
Библиотеки стандартных и нестандартных функций
На разных этапах развития программирования выдвигались различные концепции, которые могли бы обеспечить быстрое создание качественных программ, возможность компоновки больших программных систем из небольших хорошо отработанных модулей, возможность повторного использования ранее разработанных программ. Среди таких подходов можно упомянуть структурное и модульное программирование, объектно-ориентированное программирование. Следует отметить, что универсальных средств, которые бы полностью решали указанные задачи не существует и на сегодняшний день.
Однако определенные технологии получили свое развитие и в программировании, приблизив его к промышленным методам создания программных продуктов.
В этой связи мы должны вспомнить историю развития одного из мощнейших средств автоматизации программирования – разработку библиотек стандартных программ. В нашей стране в начале 60-х годов прошлого столетия на отечественных ЭВМ типа М-20 в Институте Прикладной математики АН СССР им. акад. М.В. Келдыша была разработана интерпретирующая система ИС-2, которая положила начало созданию библиотек стандартных подпрограмм, а впоследствии и стандартных алгоритмов на алгоритмических языках. Традиция эта была подхвачена журналом Ассоциации вычислительных машин (Communications of the ACM, США), который на протяжении десятков лет публиковал алгоритмы решения математических задач на языках АЛГОЛ-60 и ФОРТРАН. Публикация исходных текстов преследовала не только просветительские цели, читатели находили ошибки в опубликованных алгоритмах, предлагали более эффективные решения. Таким способом на протяжении полутора десятков лет отлаживался и накапливался архив типовых методов решения задач линейной алгебры, дифференциального и интегрального исчислений, решения нелинейных уравнений, статистической обработки данных, вычисления математических функций и т.п. Он составил основу пакета научных программ SSP (Scientific Subroutine Package) на ФОРТРАНЕ, который был взят на вооружение фирмой IBM и стал доступным для пользователей IBM/360, IBM/370. С появлением в нашей стране IBM- совместимых моделей серии ЕС ЭВМ с этим пакетом познакомились и отечественные программисты.
Современные системы программирования на базе ПК, к сожалению, не оценили вычислительные возможности пакета SSP и его расширений. Конечно, они включили в состав своих системных библиотек наиболее распространенные математические функции. Но основу сегодняшних системных библиотек составляют не методы решения математических задач. Начинка системных библиотек в BC и BCB состоит, в основном, из всякого рода сервисных программ, обеспечивающих поддержку некоторых типов данных (строки, множества, комплексная арифметика, дата и время, преобразования типов данных), управление дисплеем в текстовом и графическом режимах, обслуживание интерфейса с другими внешними устройствами и др. Те алгоритмы и программы, которые когда-то входили в состав SSP, теперь распространяются в различных коммерческих продуктах типа MathCAD, MatLab, Statistica, Mathematica и т.п.
11.1. Библиотеки системных функций в Borland C++ 3.1
Библиотеки системы BC 3.1 представлены файлами в каталоге BC\LIB. Там находится примерно 25 файлов с расширениями .lib, около двух десятков файлов с расширениями .obj и три файла с расширениями .c. Для более детального знакомства с этими файлами напомним терминологию, принятую во многих системах программирования:
- исходный модуль – текстовый файл, содержащий программу на языке программирования. Для систем BC и BCB характерны расширения .c (от названия языка C) и .cpp (от названия языка C-plus-plus);
- объектный модуль – результат обработки исходного модуля компилятором с алгоритмического языка. Для многих систем программирования файлы объектных модулей имеют расширение .obj (от object – объект). Объектный модуль – это заготовка машинной программы, которая нуждается в настройке, т.к. в работе этого модуля могут потребоваться другие модули и внешние данные;
- исполняемый модуль – результат сборки и настройки совместно работающих объектных модулей. Это – готовая к работе машинная программа, обычно имеет расширение .exe (от execute – исполнять);
- библиотечный модуль – совокупность объектных модулей, которая обычно хранится в файле с расширением .lib (от library – библиотека) или .dll (от dynamic-link library – динамически загружаемая библиотека).
Большое количество файлов, находящихся в разделе BC\LIB, объясняется тем, что некоторые библиотеки сформированы в нескольких вариантах для разных моделей памяти. В рамках MS-DOS система BC 3.1 могла создавать программы для шести разных моделей памяти – Tiny (крошечная), Small (малая), Medium (средняя), Compact (компактная), Large (большая) и Huge (огромная). Для каждой из этих моделей использовалось свое распределение памяти в пределах выделенного ресурса, использовалась своя адресация, разные типы указателей (ближние и дальние) и т.п. Поэтому ряд библиотек представлен в шести экземплярах.
Библиотека системных функций BC 3.1 условно разбита на 17 разделов, названия которых представлены в табл. 11.1. В общей сложности в этих разделах хранится порядка 600 функций.
Для обслуживания библиотек в состав системы программирования входит утилита tlib.exe. Запускается она из командной строки со следующим списком возможных параметров:
>tlib.exe lib_name [/C][/E][/P][/0] commands,listfile
Здесь
- lib_name – имя библиотечного файла, расширение .lib можно не писать;
- [/C][/E][/P][/0] – необязательные ключи режимов работы;
- commands – команды по обслуживанию библиотеки;
- listfile – список файлов.
Ключи режимов имеют следующий смысл:
- /C – в библиотеке предусмотрено различать большие и малые буквы, как это предусмотрено и стандартом языка C (по умолчанию в библиотеках большие и малые буквы не различаются);
- /E – в библиотеке будет создан расширенный словарь, который ускорит компоновку программ, использующих объектные модули из библиотеки;
- /Pnnnn – в библиотеке будет использован заданный размер "страницы" (в MS-DOS этот размер фиксирован и равен 200h);
- /0 – из объектных модулей будут удалены записи с комментариями.
Команды, набираемые в строке, состоят из одного или двух символов, вслед за которыми указывается имя объектного модуля. В имени объектного модуля разрешается опускать расширение .obj. Символ (-ы) перед именем модуля определяет действие, которое должно быть выполнено:
- + добавить модуль к содержимому библиотеки;
- – удалить модуль из библиотеки;
- * извлечь модуль из библиотеки, сохранив там его копию;
- –+ (или +– ) заменить прежний модуль в библиотеке новым;
- –* (или *– ) извлечь модуль и удалить его из библиотеки.
С помощью утилиты tlib.exe можно выдать содержимое библиотеки в указанный файл:
>tlib.exe lib_name,1.txt
По этой команде в текстовом файле 1.txt окажется список всех объектных модулей, находящихся в библиотеке lib_name с указанием их длин и меток входа. Выглядит это примерно так:
Publics by module ABS size = 14 _abs ABSREAD size = 292 _absread _abswrite ACCESS size = 55 _access ALLOCA size = 50 _alloca
11.2. Организация пользовательских библиотек
Любую функцию, написанную на языке C или C++ можно автономно откомпилировать и получить объектный модуль, который впоследствии можно присоединять к любому проекту. Естественно, что объектный модуль может оказаться полезным в последующей разработке программ, если он тщательно отлажен. Чтобы не хранить большое количество отдельных объектных файлов, их можно с помощью утилиты tlib.exe объединить в библиотеку. Любая библиотека может быть присоединена к проекту вновь разрабатываемой программы. Этими возможностями нужно обязательно пользоваться при разработке больших программных систем.
Для создания новой библиотеки достаточно добавить один или несколько объектных модулей к библиотечному файлу. Если такой библиотеки еще не было, то она будет создана. Пусть, например, в текущем каталоге находятся три объектных модуля с именами q1.obj, q2.obj и q3.obj. Для того чтобы создать в этом же каталоге новую библиотеку с именем qqq.lib, выполнить следующую команду:
>tlib qqq +q1 +q2 +q3
Если нам потребуется заменить модуль q1.obj на исправленную версию q1.obj, добавить модуль q4.obj и одновременно удалить из библиотеки модуль q2.obj, то это можно сделать следующим образом:
>tlib qqq -+q1 +q4 -q2
Если количество одновременно подключаемых модулей достаточно велико, то командной строки, ограниченной 127 символами, может не хватить. В этом случае обычно создают текстовый файл из строк вида:
+q1 +q2 +q3 ... +q15 & +q16 +q17 ... +q30 & +q31 +q32 ....
В конце каждой строки записывается символ &, который играет роль знака переноса. Если созданный таким образом файл имеет имя qq.txt, то запуск утилиты tlib выглядит следующим образом:
>tlib qqq @qq.txt
Подключение заранее изготовленных объектных модулей или извлечение нужных модулей из присоединяемых библиотек можно выполнить как в интегрированной среде, так и с помощью автономной утилиты tlink.exe, запускаемой из командной строки.
В интегрированной среде BC 3.1 файл проекта имеет расширение .prj (от project – проект). Автоматически он не создается, т.к. большинство небольших программ состоит из единственного программного файла и кроме системных компонент (библиотек и объектных модулей) ничего другого не использует. Однако в случае необходимости мы можем открыть файл проекта с помощью команды Project Open project (если он еще не существовал, то будет создан заново) и добавить к нему нужные компоненты с помощью команд Project Add item.
В интегрированной среде BCB файл проекта создается автоматически и имеет расширение .bpr (от Builder Project). Команда Add to Project в меню Project предназначена для добавления в состав проекта новых объектных модулей и библиотек.
Автономный редактор связей tlink.exe запускается из командной строки со следующим набором возможных параметров:
>tlink /k1 /k2 ,q1 q2 ,eq,mq,lib1 lib2
Здесь
- /k1 /k2... – набор ключей, управляющих работой tlink ;
- q1 q2 – список объектных модулей, включая и головную функцию main ;
- eq – имя исполняемого модуля;
- mq – имя модуля, в который записывается "карта" памяти;
- lib1 lib2 – имена подключаемых библиотек.
Перечень ключей программа tlink.exe выдает после запуска без параметров. Их расшифровка приведена в табл. 11.1. Расширения имен файлов, если они стандартные, можно опускать ( .obj – объектные модули, .exe – исполняемый модуль, .map – файл "карты" памяти, .lib – библиотечный файл). "Карта" памяти или таблица распределения памяти содержит информацию о размещении функций и глобальных переменных в сегментах памяти.
Ключ | Пояснение |
---|---|
/m | Выдача "карты" памяти со всеми общедоступными именами |
/x | Запрет вывода "карты" памяти |
/i | Инициализация всех сегментов данных |
/l | Подключение номеров строк исходных программ |
/s | Вывод подробной "карты" памяти сегментов |
/n | Отключение библиотек по умолчанию |
/d | Выдача предупреждений о дублировании имен в библиотеках |
/c | Режим различения больших и малых букв |
/3 | Разрешение использовать 32-битные операнды и команды |
/v | Сохранение дополнительной информации для отладки |
/e | Игнорирование расширенных словарей в библиотеках |
/t | Создание com-файла вместо exe-файла |
11.3. Динамически загружаемые библиотеки
В довольно ранних версиях операционных систем наряду со статическими библиотеками объектных модулей появились динамически загружаемые библиотеки с расширением .dll (от Dynamic-link libraries). Динамически загружаемые библиотеки Windows могут иметь и другие расширения – .exe или .drv.
Основная разница между статическими и динамическими библиотеками заключается в следующем. Если используется статическая библиотека, то на стадии редактирования связей в состав исполняемого модуля включаются все функции, для которых обнаружено обращение из текста исходной программы. В отличие от этого вызов модуля из динамической библиотеки происходит только на стадии выполнения программы. При таком подходе библиотечные функции не включаются в состав исполняемого модуля, его размеры становятся меньше и, тем самым, экономится место, занимаемое исполняемыми файлами на диске.
У каждого из этих подходов есть свои плюсы и минусы. При использовании статических библиотек размер исполняемого модуля возрастает, т.к. к нему подключаются все функции, упомянутые в программе. Однако такой модуль можно выполнить на любом компьютере независимо от того, установлена ли там соответствующая система программирования или нет. При использовании динамически загружаемых библиотек размер исполняемого модуля не так велик, но для его работы требуется присутствие в оперативной памяти динамической библиотеки, из которой в случае необходимости потребуется запустить тот или иной модуль. Поэтому при переносе программы на другой компьютер придется кроме исполняемого модуля захватить и всю цепочку задействованных динамических библиотек. Правда, в разумных системах программирования предусмотрен режим компиляции с включением всех вызываемых функций в состав исполняемого модуля.