Библиотека – усовершенствованный — КиберПедия 

Биохимия спиртового брожения: Основу технологии получения пива составляет спиртовое брожение, - при котором сахар превращается...

Типы сооружений для обработки осадков: Септиками называются сооружения, в которых одновременно происходят осветление сточной жидкости...

Библиотека – усовершенствованный

2021-01-29 84
Библиотека – усовершенствованный 0.00 из 5.00 0 оценок
Заказать работу

 

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

Библиотека, написанная Фредом Фишем (Fred Fish) в начале 1980‑х, была с тех пор несколько усовершенствована. Теперь она явным образом является общим достоянием, поэтому ее можно использовать без всяких проблем как в свободном, так и частном программном обеспечении. Она доступна через архив FTP Фреда Фиша[175] как в виде сжатого файла tar, так и в виде архива ZIP. Документация хорошо резюмирует:

 

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

Пакет лишь незначительно снижает скорость выполнения программ, обычно значительно менее 10%, и немного увеличивает их размеры, обычно от 10 до 20%. Определив особый идентификатор препроцессора С, можно снизить оба этих показателя до нуля без необходимости изменений в исходном коде.

Следующий список является кратким изложением возможностей пакета. Каждую возможность можно отдельно включать или отключать во время запуска программы, указав соответствующие аргументы командной строки.

• Трассировка исполнения, отображающая уровень потока управления полуграфическим способом с использованием отступов, обозначающих глубину вложения

• Вывод значений всех или любого набора ключевых внутренних переменных.

• Ограничение действий определенным набором указанных функций.

• Ограничение трассировки функций указанной глубиной вложения.

• Пометку каждой выводимой строки названием исходного файла и номером строки.

• Пометку каждой выводимой строки названием текущего процесса.

• Сохранение в стеке или восстановление состояния отладки для обеспечения исполнения со встроенными значениями по умолчанию для отладки.

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

 

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

 

Эта программа иллюстрирует большинство важных моментов. Макрос (строка 12) должен быть вызван после объявлений переменных и перед любым другим кодом. (Это потому, что он сам объявляет несколько частных переменных.[176])

Макрос (строка 13) устанавливает имя программы, главным образом, для использования в выводимых библиотекой сообщениях. Этот макрос должен вызываться лишь однажды, из.

Макрос (строка 14) заставляет библиотеку проверить указанную переменную окружения (в данном случае) на предмет управляющей строки (Управляющие строки вскоре будут рассмотрены.) Библиотека может, сохранив свое текущее состояние и использовав новое, создавать стек сохраненных состояний. Таким образом, этот макрос помещает в стек сохраненных состояний полученное от данной переменной окружения состояние. В данном примере использован случай, когда макрос создает первоначальное состояние. Если такой переменной окружения нет, ничего не происходит. (В качестве отступления, является довольно общей переменной, возможно, было бы лучше [для ].)

Макрос (строка 18) передает значение управляющей строки, полученной из опции командной строки. (Новый код должен использовать или вместо ручного анализа аргументов.) Таким образом обычно включается режим отладки, но использование переменной окружения предоставляет также дополнительную гибкость.

Макрос (строка 23) осуществляет вывод. Второй аргумент использует методику, которую мы описали ранее (см. раздел 15.4.1.1 «Используйте отладочные макросы»), по включению в скобки всего списка аргументов, делая его простым аргументом, насколько это касается препроцессора С. Обратите внимание, что завершающий символ конца строки в форматирующей строке не указывается; библиотека вставляет его за вас.

При печати по умолчанию выводит все операторы. Первый аргумент является строкой, которая может использоваться для ограничения вывода лишь теми макросами, которые используют эту строку.

Наконец, макрос (строка 28) используется вместо обычного оператора для возврата значения. Для использования с функциями имеется соответствующий макрос.

Оставшаяся часть программы заполнена функцией:

 

 

Когда программа откомпилирована и скомпонована вместе с библиотекой, ее можно запустить обычным способом. По умолчанию, программа не создает вывод отладки. Но со включенной отладкой доступны различные виды вывода:

Factorial 1 2 3

 

factorial ‑#t 1 2 3

 

 

factorial ‑#d 1 2

 

 

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

Управляющая строка состоит из набора опций и аргументов. Каждая группа опций и аргументов отделяется от других символом двоеточия. Каждая опция представлена одной буквой, а аргументы этой опции отделяются от нее запятыми. Например:

 

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

Следующий список опций и аргументов воспроизведен из руководства библиотеки. Квадратные скобки заключают необязательные аргументы. Мы включаем здесь лишь те, которые находим полезными; полный список см. в документации.

 

Разрешает вывод от макросов с указанными ключевыми словами. Пустой список ключевых слов предполагает, что выбраны все ключевые слова.

 

Помечает каждую строку вывода отладки именем исходного файла, содержащего макрос, осуществляющий вывод.

 

Идентифицирует процесс, выводящий каждую отладочную или трассировочную строку номером ID для этого процесса.

 

Помечает каждую строку вывода отладчика номером строки исходного файла, в котором находится осуществляющий вывод макрос.

 

Перенаправляет поток вывода отладчика в указанный файл. Потоком вывода по умолчанию является. Пустой список аргументов перенаправляет вывод в.

 

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

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

 

Этот макрос похож на: первый аргумент является строкой, выбранной с помощью опции, а второй – код для исполнения:

 

 

Это значение типа для использования с процедурами. Оно позволяет осуществлять собственный вывод в поток файла отладки.

 

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

 

Этот макрос выталкивает из стека один уровень сохраненного состояния отладки, созданный макросом. Он довольно эзотерический; вы скорее всего не будете его использовать.

 

Этот макрос заключает в оболочку вызов, принимая те же самые аргументы. Он позволяет библиотеке обрабатывать нелокальные переходы.

В другом воплощении, в первой начинающей компании, для которой мы работали[177], мы использовали в своем продукте библиотеку. Она была неоценимой при разработке, а опустив в конечной сборке, мы смогли построить готовую версию без других изменений исходного кода.

Чтобы извлечь максимальную выгоду от библиотеки, нужно использовать ее последовательно, по всей программе. Это проще, если вы используете ее с начала проекта, но в качестве эксперимента мы обнаружили, что с помощью простого сценария мы смогли включить библиотеку в программу с 30 000 строк кода за несколько часов работы. Если вы можете позволить себе накладные расходы, лучше всего оставить ее в конечной сборке вашей программы, чтобы можно было ее отлаживать без необходимости предварительной перекомпиляции.

Мы нашли, что библиотека является удачным дополнением к внешним отладчикам, таким, как GDB; она обеспечивает организованный и последовательный способ применения поддержки к коду С. Она также довольно элегантно сочетает многие из методик, которые мы ранее в данной главе очертили отдельно. Особенно полезна особенность динамической трассировки вызовов функций, и она доказывает свою бесценность в качестве помощи в изучении поведения программы, если вы незнакомы с ней.

 

Отладчики выделения памяти

 

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

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

• Обнаружение утечек памяти: память, которая выделяется, а затем становится недоступной.

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

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

• Обнаружение использования уже освобожденной памяти: память, которая освобождена, используется через висячий указатель.

• Обнаружение выхода за границы выделенной памяти: получение доступа или сохранение в память за пределами выделенной границы.

• Предупреждение об использовании неинициализированной памяти. (Многие компиляторы могут выдавать такие предупреждения.)

• Динамическая трассировка функций: когда появляется ошибочный доступ к памяти, вы получаете трассировку от того места, где память используется, до того места, где она была выделена.

• Управление инструментами посредством использования переменных окружения.

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

Некоторые утилиты просто записывают эти события. Другие организуют жуткое завершение программы приложения (посредством), чтобы на код‑нарушитель можно было точно указать из отладчика. Вдобавок, большинство спроектированы для работы вместе с GDB.

Некоторые инструменты требуют изменения исходного кода, такого, как вызов специальных функций или использование особого заголовочного файла, дополнительных и статической библиотеки. Другие работают посредством использования специального механизма библиотек общего пользования Linux/Unix для прозрачной установки себя в качестве заместителя стандартных библиотечных версий и.

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

 

GNU/Linux

 

Системы GNU/Linux, использующие GLIBC, предоставляют две функции для включения и отключения трассировки памяти во время исполнения.

 

 

Когда вызывается, библиотека проверяет переменную окружения. Ожидается, что она указывает на записываемый файл (существующий или нет). Библиотека открывает файл и начинает записывать сведения о выделениях и освобождениях памяти (Если файл не может быть открыт, запись не производится. Файл урезается каждый раз при запуске программы.) Когда вызывается, библиотека закрывает файл и больше не регистрирует выделения и освобождения.

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

Когда приложение завершается, вы используете программу для анализа файла журнала. (Файл журнала в формате ASCII, но информацию нельзя использовать непосредственно.) Например, включает трассировку, если определена:

export TIDYMEM=1 MALLOC_TRACE=trace.out

./gawk 'BEGIN { print "hello, world" }'

 

Mtrace./gawk mtrace.out

 

 

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

 

Electric Fence

 

В разделе 3.1 «Адресное пространство Linux/Unix» мы описали, как динамическая память выделяется из кучи, которая может расти и сокращаться (с помощью вызовов или, описанных в разделе 3.2.3 «Системные вызовы: и»).

Ну, картина, которую мы там представили, является упрощением действительности. Более развитые системные вызовы (не рассматриваемые в данной книге) позволяют добавлять в адресное пространство процесса дополнительные, необязательно смежные сегменты памяти. Многие отладчики работают с использованием этих системных вызовов для добавления новых областей адресного пространства при каждом выделении. Преимуществом этой схемы является то, что операционная система и аппаратное обеспечение защиты памяти компьютера взаимодействуют для обеспечения недействительности доступа к памяти за пределами этих изолированных сегментов, генерируя сигнал. Эта схема изображена на рис. 15.1.

Рис. 15.1. Адресное пространство Linux/Unix, включая специальные области

Первым пакетом отладки, реализовавшим эту схему, был Electric Fence. Electric Fence является вставляемым заместителем для и др. Он работает на многих системах Unix и GNU/Linux; он доступен с FTP архива его авторов.[178] Он поставляется также со многими дистрибутивами GNU/Linux, хотя, возможно, вам придется выбрать ею явным образом при установке системы.

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

 

 

Эта программа осуществляет простую проверку опций командной строки, чтобы решить, как вести себя плохо: вызывает доступ к памяти за ее выделенными страницами, а пытается использовать освобожденную память. (Строки 18 и 21 являются соответственно опасными.) Обратите внимание, что без опций указатель никогда не освобождается (строка 25), Electric Fence не перехватывает этот случай.

Одним из способов использования Electric Fence, способом, который гарантированно работает на различных системах Unix и GNU/Linux, является статическая компоновка с ним вашей программы. Затем программа должна быть запущена из отладчика. (Документация Electric Fence явно указывает, что Electric Fence не следует компоновать с двоичным файлом готового изделия.) Следующий сеанс демонстрирует эту процедуру и показывает, что происходит для обеих опций командной строки:

cc ‑g ch15‑badmem1.c ‑lefence ‑о ch15‑badmem1

gdb ch15‑badmem1

 

 

run ‑b

 

run ‑f

 

y

 

 

На системах, которые поддерживают разделяемые библиотеки и переменную окружения (в том числе и на GNU/Linux), вам не нужно явным образом компоновать библиотеку. Вместо этого сценарий оболочки организует запуск программы с соответствующей настройкой.

Хотя мы не описали механизмы подробно, GNU/Linux (и другие системы Unix) поддерживают разделяемые (shared) библиотеки, особые версии библиотечных процедур, которые хранятся в одном файле на диске, вместо того, чтобы копироваться в каждый отдельный двоичный исполняемый файл программы. Разделяемые библиотеки экономят дисковое пространство и могут сохранить системную память, поскольку все программы, использующие разделяемые библиотеки, используют одну и ту же копию библиотеки в памяти. Платой за это является замедление загрузки программы, поскольку программу и разделяемую библиотеку нужно подключить друг к другу прежде, чем программа сможет начать выполнение. (Обычно это прозрачно для вас, пользователя.)

Переменная окружения заставляет системный загрузчик программ (который загружает исполняемые файлы в память) связаться со специальной библиотекой до стандартных библиотек. Сценарий использует эту особенность для связывания набора функций в Electric Fence.[179] Таким образом, повторная компоновка даже не нужна. Этот пример демонстрирует:

cc ‑g ch15‑badmem1.c ‑о ch15‑badmem1

ef ch15‑badmem1 ‑b

 

ef ch15‑badmem1 ‑f

 

 

ls ‑l core*

 

 

GNU/Linux создает файлы, которые включают в свое имя ID процесса. В данном случае такое поведение полезно, поскольку мы можем отдельно отлаживать каждый файл:

gdb ch15‑badmem1 core.28005

 

Quit

 

gdb ch15‑badmem1 core.28007

 

Справочная страница efence (3) описывает несколько переменных окружения, которые должны быть установлены, чтобы настроить поведение Electric Fence. Следующие три наиболее примечательны.

 

Установка этой переменной в 1 заставляет Electric Fence проверять «недоборы» (underruns) вместо «переборов» (overruns) при выходе за пределы отведенной памяти. «Перебор», т.е. доступ к памяти в области за выделенной, был продемонстрирован ранее. «Недобор» является доступом к памяти, расположенной перед выделенной областью памяти.

 

Установка этой переменной в 1 предотвращает повторное использование Electric Fence памяти, которая была корректно освобождена. Это полезно, когда вы думаете, что программа может получать доступ к освобожденной памяти; если освобожденная память впоследствии была выделена заново, доступ к ней через предыдущий висячий указатель остался бы в противном случае незамеченным.

 

При наличии ненулевого значения Electric Fence допускает вызовы ''. Такие вызовы в стандартном С технически действительны, но могут представлять программную ошибку. Соответственно Electric Fence по умолчанию их запрещает.

Вдобавок к переменным окружения Electric Fence предоставляет глобальные переменные с такими же названиями. Вы можете изменить их значения из отладчика, так что можно динамически изменять поведение программы, которая уже начала выполнение. Подробности см. в efence (3).

 

Отладка Malloc:

 

Библиотека предоставляет большое число опций отладки. Ее автором является Грей Ватсон (Gray Watson), есть также и свой веб‑сайт.[180] Как и в случае с Electric Fence, она может быть уже установленной на вашей системе, или же вы можете ее извлечь и построить самостоятельно.

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

echo $DMALLOC_OPTIONS

 

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

Первый шаг заключается в определении функции оболочки с названием, которая вызывает программу драйвера:

dmalloc() {

eval 'command dmalloc ‑b $*'

}

После того, как это сделано, вы можете передать функции опции для установки файла журнала (‑1), указать число итераций, после которых должна проверить свои внутренние структуры данных (‑1), и указать уровень отладки или другой тэг ('').

dmalloc ‑1 dm‑log ‑i 100 low

Как и Electric Fence, библиотека может быть скомпонована с приложением статически или связана динамически при помощи. Последнее демонстрирует следующий пример:

LD_PRELOAD=libdmalloc.so ch15‑badmem1 ‑b

 

 

ЗАМЕЧАНИЕ. Не используйте ''! Если вы это сделаете, каждая программа, которую вы запустите, такая как, будет выполняться со включенной проверкой. Ваша система быстро станет непригодной. Если вы сделали это случайно, можете использовать '', чтобы восстановить обычное поведение.

 

Результаты записываются в файл следующим образом:

cat dm‑log

 

Вывод содержит много статистических данных, которые нам пока не интересны. Интересна строка, в которой указывается не освобожденная память, с адресом возврата, указывающим на выделившую память функцию (''). Документация объясняет, как получить расположение в исходном коде этого адреса с использованием GDB.

gdb ch15‑badmem1

 

 

X 0x8048412

 

info line *(0x8048412)

 

 

Это трудно, но выполнимо, если нет другого выбора. Однако, если вы включите в свою программу заголовочный файл "" (после всех остальных операторов), вы можете получить сведения из исходного кода непосредственно в отчете.

 

(Файл является аналогичным, за исключением того, что он включает, поэтому мы не стали беспокоиться с его отображением).

Отдельные возможности отладки включаются или выключаются посредством использования лексем (tokens) – специально распознаваемых идентификаторов – и опций для добавления лексем (свойств) или для их удаления. Имеются предопределенные комбинации, '', '' и ''. Чем являются эти комбинации, вы можете увидеть с помощью ''.

Dmalloc low

dmalloc ‑Lv

 

 

Полный список лексем вместе с кратким объяснением и соответствующим каждой лексеме числовым значением можно получить с помощью '':

dmalloc ‑DV

 

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

 


Поделиться с друзьями:

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

Типы сооружений для обработки осадков: Септиками называются сооружения, в которых одновременно происходят осветление сточной жидкости...

Археология об основании Рима: Новые раскопки проясняют и такой острый дискуссионный вопрос, как дата самого возникновения Рима...

Автоматическое растормаживание колес: Тормозные устройства колес предназначены для уменьше­ния длины пробега и улучшения маневрирования ВС при...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.093 с.