Интерпретаторы, имеющиеся для FreeBSD Тема: Введение в программирование Выполнил: Проверила: Введение в программирование Программа представляет собой набор инструкций, которые предписывают компьютеру выполнить различные действия; иногда действие, которое нужно выполнить, зависит от того, что случилось в результате выполнения предыдущей операции. Этот раздел дает вам обзор двух основных способов, которыми вы можете выдавать инструциии, или "команды", как их обычно называть. В одном способе используется интерпретатор, а в другом компилятор. Так как человеческие языки слишком трудны для недвусмысленного понимания компьютером, команды обычно записываются на одном из специально разработанных языке программирования. Интерпретаторы В случае использования интерпретатора язык представляет собой оболочку, в которой вы набираете команды, а оболочка их выполняет. Для более сложных программ вы можете набрать команды в файле и заставить интерпретатор загрузить файл и выполнить команды из него. Если что-то происходит не так, интерпретатор передает управление отладчику, с помощью которого вы решаете возникшую проблему. Плюсом этого подхода является возможность видеть результаты выполнения ваших команд немедленно, а ошибки могут быть быстро исправлены. Самый большой минус проявляется, когда вы собираетесь поделиться с кем-нибудь вашими программами. Они должны иметь точно такой же интерпретатор или вы должны каким-то образом передать его, а тем нужно понять, как его использовать. Кроме того, пользователям может не понравиться перспектива оказаться в отладчике в случае нажатия не той клавиши! С точки зрения производительности, интерпретаторы могут использовать много памяти, и, как правило, генерируемый ими код не так эффективен, как код, генерируемый компиляторами. По моему мнению, использование интерпретационных языков являются хорошим началом, если ранее вы не занимлись программированием. Такой способ работы обычно используется с языками типа Lisp, Smalltalk, Perl и Basic. Можно также отметить, что оболочка Unix (sh, csh) является интерпретатором, и многие люди пишут "скрипты" для оболочек для облегчения выполнения различных "доморощенных" задач на своих машинах. На самом деле, частью философии Unix было предоставление множества маленьких вспомогательных программ, которые можно связать вместе в скриптах оболочки для выполнения полезных действий. Интерпретаторы, имеющиеся для FreeBSD Ниже приводится список интепретаторов, которые доступны в виде пакаджей FreeBSD, с кратким обсуждением некоторых самых популярных интерпретационных языков. Для получения одного из этих пакаджей вам достаточно щелкнуть на ссылке, а затем выполнить команду # pkg_add package name пользователем root. Для работы пакаджа, как правило, требуется полнофункциональная система FreeBSD версии 2.1.0 и выше! BASIC Это сокращение от Beginner's All-purpose Symbolic Instruction Code. Разработан в 1950-х годах для обучения студентов университета прграммированию и в 1980-х поставлялся с каждым уважающим себя персональным компьютером; BASIC был первым языком программирования для многих программистов. Он лежит в основе Visual Basic. Во FreeBSD имеются Bywater Basic Interpreter и Phil Cockroft's Basic Interpreter (ранее Rabbit Basic) в виде пакаджей FreeBSD Lisp Язык, который был разработан в конце 1950-х в качестве альтернативы "вычислительным" языкам, популярным в то время. Вместо того, чтобы опираться на вычисления, List опирается на списки; на самом деле название является сокращением от "List Processing". Очень популярен в области AI (Искуственного Интеллекта). Lisp является очень мощным и многообразным языком, но он может оказаться достаточно большим и громоздким. Во FreeBSD имеется GNU Common Lisp в виде пакаджа. Perl Очень часто используется системными администраторами для написания скриптов; также часто используется на серверах World Wide Web для написания CGI-скриптов. Самая последняя версия (версия 5) поставляется с FreeBSD. Scheme Диалект языка Lisp, более компактный и понятный, чем Common Lisp. Популярен в университетах, так как достаточно прост для обучения аспирантов в качестве первого языка и имеет достаточно высокий уровень для использования в исследовательской работе. Во FreeBSD имеются пакаджи для Elk Scheme Interpreter, MIT Scheme Interpreter и SCM Scheme Interpreter. Icon The Icon Programming Language. Logo Brian Harvey's LOGO Interpreter. Python Python Object-Oriented Programming Language Компиляторы Компиляторы достаточно сильно отличаются от интерпретаторов. Сначала вы записываете свой код в файл (или файлы), используя редактор. Затем вы запускаете компилятор и смотрите, воспринимает ли он вашу программу. Если она не компилируется, вы скрежещете зубами и возвращаетесь к редактированию; если код компилируется и программа выдается, вы можете запустить ее в приглашении оболочки или в отладчике для проверки правильности работоспособности. [1] Обычно этот процесс не так непосредственен, как при использовании интерпретатора. Однако он позволяет вам выполнять множество действий, которые затруднительно или невозможно сделать в интерпретаторе, к примеру, написать код, тесно взаимодействуюший с операционной системой--или даже написать собственную операционную систему! Это также полезно, если вам нужно написать очень эффективный код, так как компилятор может затратить время на оптимизацию кода, что может оказаться неудобным для интерпретатора. Кроме того, распространить программу, написанной для компилятора, обычно проще, чем для интерпретатора--вы можете просто предоставить копию выполнимого файла, полагая, что используется та же операционная система, что и у вас. В число компиляционных языков входят Pascal, C и C++. C и C++ являются непрощающими ошибки языками, и больше подходят для опытных программистов; Pascal, с другой стороны, разрабатывался как язык для обучения, и хорош для начала. К сожалению, во FreeBSD язык Pascal не поддерживается, если не считать конвертера Pascal-в-C в портах. Так как цикл редактирование-компиляция-запуск-отладка неудобен при использовании отдельных программ, многие производители коммерческих компиляторов предлагают интегрированные среды разработки (сокращенно IDE - Integrated Development Environment). Во FreeBSD нет IDE такого рода; однако для этих целей возможно использование редактора Emacs. Это обсуждается в Section 2.7. Компиляция при помощи cc Этот раздел касается только GNU-компилятора для C и C++, так как он поставляется вместе с системой FreeBSD. Он может быть вызван командами cc или gcc. Подробности по генерации программ с помощью интерпретатора зависят от конкретного интерпретатора и обычно хорошо описываются в документации и встроенной системе помощи интерпретатора. Как только вы напишете свое творение, следующим шагом является преобразование его в нечто, что будет (надеемся!) запускать во FreeBSD. Это обычно происходит в несколько шагов, каждый из которых делается отдельной программой. - Предварительная обработка исходного кода для удаления комментариев и выполнения других хитростей, наподобие раскрытия макросов в языке C.
- Синтаксическая проверка вашего кода на предмет выявления несоответствий правилам языка. Если таковые обнаружились, об этом будет сообщено!
- Преобразование исходного кода в код на языке ассемблера--он очень близок к машинному коду, но все еще понятен человеку. Определенно. [1]
- Преобразование ассемблерного кода в машинный код--да, мы имеем в виду биты и байты, здесь только нули и единицы.
- Проверка на то, что вы использовали такие вещи, как функции и глобальные переменные правильно. Например, если вы обращались к несуществующей функции, на это будет указано.
- Если вы пытаетесь получить выполнимый файл из нескольких файлов с исходными текстами, работа над тем, как их объединить.
- Работа над генерацией того, что загрузчик сможет загрузить в память и запустить.
- Наконец, запись выполнимого файла в файловую систему.
Термин компиляция часто используется для обозначения действий на шагах от 1 до 4--остальные шаги называют компоновкой. Иногда шаг 1 называют препроцессорной обработкой, а шаги 3-4 ассемблированием. К счастью, почти все эти детали скрыты от вас, cc как конечная программа управляет за вас вызовом всех этих программ с правильными аргументами; простой вызов % cc foobar.c приведет к компиляции foobar.c посредством всех шагов выше. Если у вас имеется для компиляции больше одного файла, просто сделайте нечто вроде следующего % cc foo.c bar.c Заметьте, что синтаксическая проверка--это именно проверка синтаксиса. При этом не выполняется проверка на наличие сделанных вами логических ошибок, типа вхождения в бесконечный цикл или использования пузырьковой сортировки там, где вы хотели использовать двоичную. [2] Имеется огромное количество параметров для cc, все они описаны на справочной странице. Вот несколько из самых важных, с примерами их использования. -o filename Имя выходного файла. Если вы не используете этот параметр, cc сгенерирует выполнимый файл с именем a.out. [3] % cc foobar.c выполнимый файл называется a.out % cc -o foobar foobar.c выполнимый файл называется foobar -c Выполнить только компиляцию файла, без компоновки. Полезно для игрушечных программ, когда вы хотите просто проверить синтаксис, или при использовании Makefile. % cc -c foobar.c В результате будет сгенерирован объектный файл (не выполнимый файл) с именем foobar.o. Он может быть скомпонован с другими объектными файлами для получения выполнимого файла. -g Создать отладочную версию выполнимого файла. Этот параметр указывает компилятору поместить в выполнимый файл информацию о том, какая строка какого файла с исходным текстом какому вызову функции соответствует. Отладчик может использовать эту информацию для вывода исходного кода при пошаговом выполнении программы, что очень полезно; минусом является то, что вся эта дополнительная информация делает программу гораздо большей. Обычно вы компилируете с параметром -g при работе над программой, а затем, когда убедитесь в работоспособности программы, компилируете "окончательную версию" без параметра -g. % cc -g foobar.c При этом будет сгенерирована отладочная версия программы. [4] -O Создать оптимизированную версию выполнимого файла. Компилятор прибегает к различным ухищрениям для того, чтобы сгенерировать выполнимый файл, выполняющийся быстрее, чем обычно. После опции -O вы можете добавить число, указывающее качество оптимизации, но использование этого не защищено от ошибок оптимизации компилятора. Например, известно, что версия компилятора cc, поставляемая с FreeBSD версии 2.1.0, при некоторых условиях генерирует неверный код при использовании опции -O2. Обычно оптимизацию используют при компиляции окончательной версии. % cc -O -o foobar foobar.c По этой команде будет создана оптимизированная версия программы foobar. Следующие три флага заставят cc проверять ваш код на соответствие известному международному стандарту, часто называемому стандартом ANSI, хотя, строго говоря, это стандарт ISO. -Wall Включить выдачу всех предупреждений, которые посчитают нужным выдать авторы cc. Несмотря на свое название, при этом включается выдача не всех предупреждений, на которые способен компилятор cc. -ansi Выключить большинство, если не все, не-ANSI расширений языка C, имеющиеся в cc. Несмотря на название, этот параметр не гарантирует, что ваш код будет строго соответствовать стандарту. -pedantic Выключить все расширения C, имеющиеся в компиляторе cc, не соответствующие стандарту ANSI. Без этих флагов компилятор cc позволит вам использовать некоторые нестандартные расширения языка. Некоторые из них весьма полезны, но не будут работать при использовании других компиляторов--фактически одним из назначений стандарта является обеспечение возможности писать код, который будет работать с любым компилятором в любой системе. Такой код называется переносимым кодом. Вообще говоря, вы должны стараться писать как можно более переносимый код, иначе вам позже, может быть, придется полностью переписывать программу, чтобы заставить ее работать где-то еще--и кто знает, что вы будете использовать через несколько лет? % cc -Wall -ansi -pedantic -o foobar foobar.c По этой команде после проверки на соответствие стандарту файла foobar.c будет сгенерирован выполнимый файл foobar. -llibrary Задает библиотеку функций, которая будет использоваться на этапе компоновки. В качестве самого распространенного примера можно привести компиляцию программы, использующей некоторые математические функции на языке C. В отличие от других платформ, имеется отделенная от стандартной библиотека, и вам нужно указать компилятору, что ее нужно использовать. При этом если библиотека называется libsomething.a, вы передаете программе cc аргумент -lsomething. Например, математическая библиотека называется libm.a, так что вы передаете программе cc аргумент -lm. Известной "хитростью" при работе с математической библиотекой является то, что в командной строке она должна быть указана в качестве последней библиотеки. % cc -o foobar foobar.c -lm По этой команде библиотека математических функций будет скомпонована с foobar. Если вы компилируете код на языке C++, вам нужно добавить параметр -lg++, или -lstdc++ при использовании FreeBSD 2.2 и выше, к аргументам командной строки для компоновки библиотеки функций C++. Либо вы можете запустить вместо cc компилятор c++, который сделает это за вас. Во FreeBSD c++ может быть вызван как g++. % cc -o foobar foobar.cc -lg++ For FreeBSD 2.1.6 and earlier % cc -o foobar foobar.cc -lstdc++ For FreeBSD 2.2 and later % c++ -o foobar foobar.cc В каждом из этих вариантов из файла foobar.cc с исходным кодом C++ будет создан выполнимый файл foobar. Заметьте, что в Unix-системах файлы с исходным кодом C++ традиционно оканчиваются на .C, .cxx или .cc, в отличие от стиля MS-DOS .cpp (который уже использовался для чего-то еще). gcc использует это для определения того, какой компилятор использовать; однако это ограничение больше не имеет силы, так что вы можете безнаказанно называть ваши файлы с кодом C++ .cpp! 2.4.1. Часто возникающие вопросы и проблемы с cc 2.4.1.1. Я пытаюсь написать программу, которая использует функцию sin() и получаю такую ошибку. Что она означает? 2.4.1.2. Все замечательно, чтобы попрактиковаться в использовании параметра -lm, я написал вот такую простую программу. Все, что она делает, заключается в возведении числа 2.1 в шестую степень. 2.4.1.3. Так как это исправить? 2.4.1.4. Я компилировал файл с именем foobar.c, но не могу найти выполнимый файл с именем foobar. Куда он подевался? 2.4.1.5. Хорошо, у меня получился выполнимый файл с именем foobar, я могу видеть его при запуске команды ls, но когда я набираю в командной строке foobar, выдается сообщение об отсутствии такого файла. Почему он не может быть найден? 2.4.1.6. Я назвал мой выполнимый файл test, но при попытке его запустить ничего не происходит. В чем дело? 2.4.1.7. Я откомпилировал мою программу, и сначала она работала нормально, но потом выдалось сообщение об ошибке с сообщением ``core dumped''. Что это означает? 2.4.1.8. Очаровательно, но что я теперь должен делать? 2.4.1.9. Когда моя программа сбрасывает дамп, она выдает сообщение ``segmentation fault''. Что это такое? 2.4.1.10. Иногда при получении дампа памяти выдается сообщение ``bus error''. В моей книге про Unix утверждается, что это является признаком проблемы с оборудованием, но компьютер работает нормально. Это правда? 2.4.1.11. Эти дампы памяти, если подумать, могут оказаться весьма полезными, если я смогу получать их, когда захочу. Могу ли я это делать, или мне нужно ждать появления ошибки? 2.4.1.1. Я пытаюсь написать программу, которая использует функцию sin() и получаю такую ошибку. Что она означает? /var/tmp/cc0143941.o: Undefined symbol `_sin' referenced from text segment При использовании таких математических функций, как sin(), вам нужно указать компилятору cc на компоновку с математической библиотекой, вот так: % cc -o foobar foobar.c -lm 2.4.1.2. Все замечательно, чтобы попрактиковаться в использовании параметра -lm, я написал вот такую простую программу. Все, что она делает, заключается в возведении числа 2.1 в шестую степень. #include <stdio.h> int main() { float f; f = pow(2.1, 6); printf("2.1 ^ 6 = %f\n", f); return 0; } и я компилирую ее вот так: % cc temp.c -lm как вы и сказали, но при ее запуске получаю вот что: % ./a.out 2.1 ^ 6 = 1023.000000 Это неправильный результат! Что происходит? Когда компилятор видит, что вы вызываете функцию, он пытается найти для нее объявление. Если его нет, то предполагается, что функция возвращает значение типа int, что определенно не является тем, что вы имели в виду. 2.4.1.3. Так как это исправить? Объявления математических функций находятся в файле math.h. Если вы включаете этот файл, то компилятор сможет найти объявление и перестанет вытворять странные вещи с вашими расчетами! #include <math.h> #include <stdio.h> int main() { ... После компиляции таким же образом, как и раньше, запустите программу снова: % ./a.out 2.1 ^ 6 = 85.766121 Если вы используете какие-либо математические функции, всегда включайте файл math.h и не забудьте выполнить компоновку с математической библиотекой. 2.4.1.4. Я компилировал файл с именем foobar.c, но не могу найти выполнимый файл с именем foobar. Куда он подевался? Запомните, что cc будет называть выполнимый файл a.out, если вы не зададите имя явно. Воспользуйтесь опцией -o filename: % cc -o foobar foobar.c 2.4.1.5. Хорошо, у меня получился выполнимый файл с именем foobar, я могу видеть его при запуске команды ls, но когда я набираю в командной строке foobar, выдается сообщение об отсутствии такого файла. Почему он не может быть найден? В отличие от MS-DOS, Unix не просматривает текущий каталог, когда пытается найти выполнимый файл, который вы хотите запустить, если вы явно его укажете. Либо введите команду ./foobar, которая означает, что "нужно запустить файл с именем foobar, располагающийся в текущем каталоге", или измените вашу переменную окружения PATH, чтобы она выглядела примерно как bin:/usr/bin:/usr/local/bin:. Точка в конце означает "посмотреть в текущем каталоге, если в других ничего не найдено". 2.4.1.6. Я назвал мой выполнимый файл test, но при попытке его запустить ничего не происходит. В чем дело? В большинстве Unix-систем в каталоге /usr/bin присутствует программа с именем test и до того, как оболочка доберется до текущего каталога, она выбирает именно ее. Наберите: % ./test либо выберите более подходящее для вашей программы имя! 2.4.1.7. Я откомпилировал мою программу, и сначала она работала нормально, но потом выдалось сообщение об ошибке с сообщением ``core dumped''. Что это означает? Фраза core dump (сброс дампа) своим происхождением обязана ранним дням Unix, когда в качестве устройств для хранения данных в машинах использовалась память на магнитных сердечниках (core). В общем, если в программе при некоторых условиях возникала ошибка, система записывала содержимое памяти на магнитных сердечниках на диск в файл с именем core, в котором затем для обнаружения причины происшедшего мог покопаться программист. 2.4.1.8. Очаровательно, но что я теперь должен делать? Для анализа дампа воспользуйтесь программой gdb (посмотрите Section 2.6). 2.4.1.9. Когда моя программа сбрасывает дамп, она выдает сообщение ``segmentation fault''. Что это такое? В основном это значит, что ваша программа пыталась выполнить в памяти какую-то недопустимую операцию; Unix построен так, что защищает операционную систему и другие программы от некорректно работающих программ. Часто встречаемыми причинами этого являются: - Попытка записи в область памяти, на которую ссылается указатель со значением NULL, например
- char *foo = NULL;
- strcpy(foo, "bang!");
- Использование указателя, Using a pointer that hasn't been initialised, eg
- char *foo;
- strcpy(foo, "bang!");
Указатель будет иметь некоторое случайное значение, которое, бывает, указывает на область памяти, недоступную вашей программе, и ядро будет прерывать вашу программу до того, как она успеет испортить что-то. Если вам не повезет, то он будет ссылаться на область где-то в вашей собственной программе, и испортит одну из ваших структур данных, что приводит к неожиданным сбоям. - Попытка выхода за границы массива, к примеру
- int bar[20];
- bar[27] = 6;
- Попытка произвести запись в область памяти, доступную только в режиме чтения, например,
- char *foo = "My string";
- strcpy(foo, "bang!");
Компиляторы Unix часто размещают строковые выражения типа "My string" в областях памяти, доступных только для чтения. - Выполнение сомнительных операций с функциями malloc() и free(), например
- char bar[80];
- free(bar);
или char *foo = malloc(27); free(foo); free(foo); Допущение какой-либо из этих ошибок не всегда приводит к ошибке, но допускать такие ошибки не нужно. Некоторые системы и компиляторы менее строги, чем другие, вот почему программы, прекрасно работающие в одной системе, могут не запускаться в другой. 2.4.1.10. Иногда при получении дампа памяти выдается сообщение ``bus error''. В моей книге про Unix утверждается, что это является признаком проблемы с оборудованием, но компьютер работает нормально. Это правда? Нет, к счастью, нет (если, конечно, у вас действительно нет проблем с оборудованием...). Обычно это является еще одним способом сказать, что вы обращаетесь к памяти неправильным образом. 2.4.1.11. Эти дампы памяти, если подумать, могут оказаться весьма полезными, если я смогу получать их, когда захочу. Могу ли я это делать, или мне нужно ждать появления ошибки? Да, просто, перейдя на другую консоль или xterm, выдайте команду % ps для определения идентификатора процесса, соответствующего вашей программе, и выполните команду % kill -ABRT pid где pid тем самым идентификатором процесса, который вы нашли. Это полезно, если ваша программа, например, входит в бесконечный цикл. Если ваша программа перехватывает сигнал SIGABRT, есть несколько других сигналов, которые приводят к подобному результату. Notes [1] | Строго говоря, cc на этом шаге преобразует исходный код в собственный машинно-независимый p-код, а не в язык ассемблера. | [2] | Если вы не знаете, то двоичная сортировка эффективна, а пузырьковая неэффективна. | [3] | Причины этого следует искать в исторических летописях. | [4] | Заметьте, что мы не использовали флаг -o для указания имени выполнимого файла, поэтому получим выполнимый файл с именем a.out. Получение отладочной версии с именем foobar оставляется читателю в качестве упражнения! | |