Розширені можливості IBM Rational Purify: налаштування звітів та інструментів Purify, Різне, Програмування, статті

IBM Rational Purify – це інструмент для точного виявлення помилок, пов’язаних з порушенням цілісності інформації в пам’яті, які дуже важко проаналізувати і виправити іншим способом. У цій статті ми розповімо про те, як використовувати опції і директиви Purify, щоб пристосувати цей інструмент для потреб вашого застосування.

IBM Rational Purify – це поліпшене засіб виявлення помилок пам’яті, яке допомагає швидко і точно локалізувати проблеми, пов’язані з порушенням цілісності інформації. Після оснащення додатка засобами Purify і його запуску Purify ретельно досліджує кожне звернення до пам’яті та повідомляє про будь-яку помилку цілісності даних ще до її виникнення. Ви можете дізнатися про різні типи помилок пам’яті і те, як використовувати Purify для їх виявлення, з попередньої статті: Navigating “C” in a “leaky” boat? Try Purify (“пливе за мовою С в дірявому човні? Спробуйте Purify.”).


На додаток до створення звіту про помилки пам’яті, Purify включає кілька розширених функцій. Вони дозволяють налаштувати використання Purify в складному середовищі для розробки програмного забезпечення. У цій статті ми спочатку дамо загальний огляд опцій і директив Purify. Потім ви дізнаєтеся, як використовувати їх для настройки наступних аспектів Purify.



Опції Purify


Purify надає широкий набір опцій. Вони надають вам можливості точного управління використанням Purify. Опції діляться на два типи:



Опції періоду збірки необхідно використовувати під час оснащення засобами Purify. Наприклад, якщо ви не хочете робити в своїй програмі перевірку переповнення буфера, то при оснащенні засобами Purify можна використовувати опцію -static-checking.







$ purify -static-checking=no cc your_prog.c


Опції періоду виконання впливають, як випливає з назви, на поведінку програми в період її виконання. Наприклад, можна вказати засобам Purify показувати у звітах про помилки більш довгі ланцюжки викликів стека:







$ purify -chain-length=10 cc your_prog.c


На додаток до прапорів, в рядку виклику опції періоду виконання і збірки можна вказати за допомогою змінних оточення PUREOPTIONS і PURIFYOPTIONS.



Раніше зазначені опції можна встановити в оболонках sh, ksh або bash наступним чином:







$ export PURIFYOPTIONS=”-static-checking=no -chain-length=10″


В оболонках csh або tcsh можна використовувати наступну опцію:







% setenv PURIFYOPTIONS “-static-checking=no -chain-length=10”


Для опцій збірки зазначені в рядку виклику значення перевизначають значення тієї ж опції, зазначені у змінній оточення. Всі опції періоду виконання (вказані за допомогою рядка виклику або змінною оточення), що використовуються при запуску забезпеченою засобами Purify програми, зберігаються в самій програмі. Під час виконання будь-яка опція періоду виконання, зазначена у змінній оточення, перевизначає значення тієї ж опції, яка зберігається в оснащеної програмі (якщо тільки не використана опція періоду збірки -ignore-runtime-environment ).


Якщо ви віддаєте перевагу інший спосіб, то в якості альтернативи можна вказати опції періоду виконання з допомогою графічного інтерфейсу користувача Purify. В цьому випадку ці значення перевизначають значення тих же опцій, зазначених за допомогою змінних оточення і рядки виклику.


Purify пропонує кілька опцій періоду збірки, щоб отримати доступ до довідки та інформації про версії:







$ purify -version


$ purify -usage


$ purify -help


$ purify -onlinehelp


Інший корисною опцією збірки є -print-home-dir . Вона друкує ім’я каталога, де встановлений пакет Purify. Її можна використовувати, наприклад, щоб запустити сценарій purify_what_options . Він дозволяє дізнатися, які опції були використані під час оснащення:







$ `purify -print-home-dir`/purify_what_options <your_prog.pure>


Іншим цікавим варіантом використання цієї опції є компіляція програми, яка включає файл purify.h для доступу до Purify API. Файл заголовків з’являється в домашньому каталозі Purify, і ця команда буде містити цей каталог в шляху пошуку підключаються файлів, який вказується для компілятора:







$ cc -c -I`purify -print-home-dir` your_prog.c


Директиви Purify


Крім опцій командного рядка, Purify дозволяє вказати різні директиви для тонкої настройки обладнання та звітів про помилки. Директиви допомагають налаштувати використання Purify для конкретного проекту. Наприклад, розглянемо ситуацію, коли виникає помилка пам’яті (скажімо, неініціалізовані читання пам’яті, або UMR) в одній з функцій (foo, наприклад) в бібліотеці стороннього розробника (наприклад, libfoo), яка використовується в проекті. Цю помилку ви виправити не можете. Ймовірно, все, що вам залишається, – це відправити звіт про помилку виробнику бібліотеки і чекати виправлення. Якщо ви не хочете бачити цю помилку у звіті Purify, оскільки виправити її неможливо, можна вказати директиву suppress:







suppress umr foo


Це вказує Purify не показувати помилки UMR у функції foo. Щоб побачити помилки, приховані директивами suppress, потрібно в графічній оболонці Purify з меню View вибрати пункт Suppressed. Purify дозволяє точно вказувати, що ви хочете бачити. Ось кілька прикладів.








suppress umr printf; foo; bar; main








suppress umr …; foo; …; main








suppress umr “libfoo*”








suppress umr *


Purify обробляє директиви, зазначені в файлах з назвою .purify в наступних каталогах і в наступному порядку:


1.     <purify-installation-home>/.purify


2.     <users-home-dir>/.purify


3.     <current-working-directory>/.purify


В залежності від того, для чого призначена ваша настройка (для всіх користувачів Purify, для всіх ваших проектів або тільки для одного з проектів), можна редагувати одне з цих полів і додавати туди директиви.


Або можна обрати в графічній оболонці Purify одну з тих помилок, які потрібно придушувати, клацнути на ній правою кнопкою миші. У контекстному меню виберіть пункт Suppress. З’явиться діалогове вікно, показане на рис. 1. У ньому можна вказати тип помилки, ланцюжок виклику і т.д. Можна зробити придушення постійним, вказавши місце розташування відповідного файлу. Purify і натиснувши кнопку Make permanent.


Рисунок 1. Діалогове вікно Purify Suppression.


 

Інша директива, kill, Працює в точності аналогічно директиві suppress. Відмінність полягає в тому, що в першому випадку повідомлення недоступні в графічному інтерфейсі, навіть якщо використовувати меню View > Suppressed Messages. Якщо помилка відбувається багаторазово (тисячі або десятки тисяч разів), то програма буде працювати швидше, якщо замість придушення застосуєте директиву kill.


Управління кешем


При оснащенні програми засобами Purify також оснащуються всі бібліотеки, від яких прямо або побічно залежить програма (наприклад, libc), а програма прив’язується до цих зміненим бібліотекам замість оригінальних. Якщо каталог, що містить бібліотеку, доступний на запис, Purify створює оснащену версію бібліотеки в тому ж каталозі. В іншому випадку вона створюється в області установки Purify, в каталозі для кешування, використовуваному за умовчанням.


Є кілька опцій збірки, що мають відношення до кешу. Наприклад, якщо ви не хочете, щоб оснащені бібліотеки були розкидані по різних каталогах, де розташовувалися їхні вихідні версії, а, навпаки, ви хочете зберігати їх у каталозі кешування, то можна використовувати опцію -always-use-cache-dir . Також можна вказати обраний каталог для кешування замість того, щоб використовувати каталог, заданий за замовчуванням. Для цього використовується наступна опція: -cache-dir=<dir-name> . За допомогою цих опцій можна видалити всі оснащені бібліотеки з кешу, просто видаливши вказаний каталог для кешування.


При оснащенні програми Purify оснащує бібліотеку тільки в тому випадку, якщо вона була змінена з моменту останнього оснащення, або якщо неможливо знайти оснащену версію бібліотеки. Це допомагає заощадити час. Якщо ви не хочете використовувати вже оснащені версії бібліотек, то можна використовувати опцію збірки -force-rebuild , І Purify заново обробить всі потрібні бібліотеки. Це корисно, якщо ви вирішили використовувати розширені опції оснащення (наприклад, -static-checking-guardzone ), І хочете повторно примусово провести обробку бібліотек.


Як правило, не можна оснастити програму на одному комп’ютері, а потім запускати її на іншому. Причина дуже проста. Програма залежить звичайно від системних бібліотек (наприклад, libc). Ці бібліотеки можуть на різних комп’ютерах відрізнятися, зокрема, через версії пакетів виправлень у різних операційних системах. Щоб гарантувати, що кожна програма отримує доступ до оснащеним бібліотекам, відповідним вихідним бібліотекам в тій же самій системі, механізм кешування в Purify організовує оснащені бібліотеки на основі імені хоста. Крім того, ваша програма може також залежати від деяких бібліотек, написаних вами або сторонніми виробниками, які однакові на всіх комп’ютерах або навіть спільно використовуються з одного мережного ресурсу. У подібній ситуації ви можете не захотіти, щоб в кеші перебувало кілька оснащених версій цих бібліотек для кожного імені хоста, оскільки ці копії будуть ідентичні, та їх зберігання – це просто трата дискового простору. Цього можна уникнути, використовуючи механізм repure в Purify на платформах IBM ® AIX ®, Linux ® і Solaris ® UNIX ®. При цьому потрібно під час оснащення подбати про кілька речей.


1. По-перше, виберіть шлях, який існує на всіх машинах. Причому реальне місце, на яке вказує цей шлях, має бути для кожної машини локальним. Наприклад, каталог /tmp існує на всіх комп’ютерах з системою UNIX ®, але він завжди локальний і спільно двома машинами ніколи не використовується. Рада. Не використовуйте шляху (наприклад, свій домашній каталог або інші подібні місця), які видно іншим комп’ютерам через мережеву інформаційну службу (Network Information Service, NIS) або мережеву файлову систему (Network File System, NFS).


2. Опція -local-cache-dir вкаже Purify зберігати оснащені бібліотеки, специфічні для системи, в місці, на яке вказує, наприклад, наступний шлях:







$ purify -always-use-cache-dir -local-cache-dir=/tmp -cache-dir=./cache


      cc -g test.c -o test.pure


3. Ви можете запустити оснащену програму на тому ж комп’ютері:







$ ./test.pure


4. Якщо ви хочете запустити оснащену програму на іншому комп’ютері, просто “переочістіте” її на іншій машині за допомогою команди repure:







$ repure ./test.pure


5. Після використання команди repure можна запустити програму також і на іншій машині:







$ ./test.pure


6. Повторіть етап з командою repure (Крок 4) для кожного комп’ютера, на якому ви хочете запускати оснащену програму.


Старі оснащені файли можна вичистити за допомогою сценарію pure_remove_old_files , Розташованого в домашньому каталозі встановленого пакету Purify:







`purify -print-home-dir`/pure_remove_old_files <path> <days>


Ця команда лише видаляє оснащені копії бібліотек: файли, чиї імена містять _pure_ , І які закінчуються специфічними для спільно використовуваних бібліотек розширеннями, наприклад, .so або .sl . Наприклад, можна вичистити все оснащені файли, які старші 14 днів і зберігаються в будь-якому місці файлової системи. Це робиться наступною командою:







$ pure_remove_old_files / 14


Фрагменти Purify


Робота Purify полягає в оснащенні коду і вставці нових інструкцій в потрібні місця програми для перевірки правильності доступу до пам’яті. Перевірка та супровід даних, необхідних для перевірки, призводить до падіння швидкості роботи. Іноді може знадобитися перевірка помилок пам’яті тільки в окремих компонентах програми. Наприклад, в бібліотеці стороннього розробника, яку використовує додаток, перевірка помилок пам’яті може не турбуватися. У подібних випадках можна оснастити додаток засобами перевірки лише вибірково, виключивши непотрібні спільно використовувані бібліотеки. Цей механізм дозволяє оснастити важливі компоненти коду навіть дуже великого додатки, одночасно підвищивши швидкість роботи оснащеного програми.


Примітка:
Вибіркове оснащення працює тільки на платформах HP-UX і AIX. На платформі Solaris SPARC воно підтримується з обмеженнями, а на платформах Solaris x86 і Linux не підтримується зовсім.


При виключенні спільно використовуваної бібліотеки Purify як і раніше перевіряє в виділяється неї пам’яті помилки управління динамічним розподілом, наприклад, витоку пам’яті.


Ось як можна виключити бібліотеку за допомогою опції selective:







$ purify -selective -exclude-libs=libfoo1.so:libfoo2.so cc -g app.c


      -o a.out.pure -lfoo1 -lfoo2 -lbar


Можна використовувати опцію -exclude-libs та надати список бібліотек (розділений двокрапками), які потрібно виключити. В якості альтернативи можна використовувати директиву exclude у файлі директив .purify :







exclude libfoo*


Як уже пояснювалося, в директивах зірочка (*) інтерпретується як будь-яку кількість входжень будь-якого символу


Опція -selective змушує Purify використовувати більш надійні алгоритми для виявлення і виключення помилкових помилок. Вони можуть виникати через виключення деяких бібліотек. Наприклад:




Ці два приклади характеризують баланс між скороченням часу виконання при запуску оснащеної версії програми і охопленням виявляються помилок. Тому потрібно все ретельно зважити і вирішити, які спільно використовувані бібліотеки виключити. Для цього потрібно детально вивчити роль, яка бібліотека відіграє в додатку, і характер її взаємодії з додатком, в якому задіяна пам’ять.


Purify може визначити помилки переповнення буфера навіть в коді, не оснащеному засобами перевірки. Але це станеться не тоді, коли помилка, власне, відбувається, а пізніше, при звільненні буфера. Purify видає повідомлення про помилки при їх виникненні. Але оскільки у Purify немає можливості вставити команди перевірки в неоснащені код, до звіту не потрапляють ніякі помилки, пов’язані з цим кодом. Якщо використовувати опцію -late-detect-logic , То Purify буде виконувати додаткові перевірки при звільненні блоку динамічно розподіляє пам’яті. При виявленні переповнення буфера Purify видасть повідомлення про помилку, пов’язаної зі спробою записи поза виділеного блоку пам’яті (Array Bound Write Late, ABWL).


Помилки управління динамічно розподіляє пам’яттю


Purify пропонує кілька опцій для контролю використання пам’яті і часу виконання оснащеної програми. Коли програма звільняє блок пам’яті, Purify не звільняє цю пам’ять негайно. Замість цього звільнений блок ставиться в чергу типу “перший увійшов – першим вийшов” (First In-First Out, FIFO). Це дозволяє Purify виявляти “повисли” (тобто вказують на неіснуючі об’єкти) покажчики. Вони виникають, коли програма намагається отримати доступ до пам’яті вже після її звільнення. Це так звані помилки читання-запису звільненої пам’яті (Free Memory Read / Write, FMR / FMW). Якщо б ми дозволили звільнити блок відразу назад в “купу”, то пам’ять б можна було відразу після цього повторно використовувати. Тоді у Purify не було б можливості розрізнити неправильний доступ до старого блоку і правильний доступ до нового блоку.


За замовчуванням довжина черги становить 100. Коли черга заповнюється, Purify звільняє перший блок в черзі і додає в неї знову звільнений блок. Довжину черзі можна поміняти за допомогою опції -free-queue-length=<value> . Більш довга черга збільшує час, протягом якого будуть надійно виявлені “повисли” покажчики на звільнену пам’ять. Однак збільшення довжини черги також змушує програму використовувати більше пам’яті (реальної чи віртуальної), оскільки дії з вільною пам’яттю відкладаються. Таким чином, збільшення довжини черги підвищує ймовірність виявлення “повислих” покажчиків, але це досягається ціною більшої витрати пам’яті.


Вільна чергу використовується тільки для маленьких блоків. Під маленькими розуміються блоки, що не перевищують певного розміру. Великі блоки звільняються відразу назад в “купу”, щоб уникнути ризику перевитрати пам’яті. Можна за допомогою опції -free-queue-threshold=<value> вказати граничне значення для приміщення блоку пам’яті в чергу. За замовчуванням це значення становить 10000 байт. Будь блок пам’яті, що перевищує це значення, звільняється негайно.


В кінці програми Purify повідомляє про всі витоках пам’яті. Якщо ви також хочете бачити всі використовувані блоки пам’яті, це можна вказати за допомогою опції -inuse-at-exit=yes . Аналогічно, щоб знайти в кінці програми використовуються дескриптори файлів, можна використовувати опцію -fds-inuse-at-exit=yes .


В системі AIX, якщо вам цікаві лише витоку пам’яті, можна використовувати опцію -memory-leaks-only. Тоді Purify справить лише дуже незначна оснащення, призначене тільки для виявлення витоків пам’яті та інших помилок управління динамічною пам’яттю, наприклад, помилок Freeing Memory Mismatch (FMM). В цьому випадку програма буде працювати набагато швидше, оскільки Purify не буде робити своєї звичайної перевірки при кожному доступі до пам’яті.


Резюме


У цій статті ви дізналися про опціях і директивах Purify, про їх використанні для управління кешем Purify, про збільшення часу роботи і використовуваної динамічної пам’яті оснащується програми. Це допоможе вам найкращим чином налаштувати Purify для певної програми.


Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*