- •Міністерство освіти і науки України
- •Жуковецька с.Л., Шестопалов с.В.
- •Анотація
- •Введення
- •Лабораторна робота №1 Технологія розробки програм у середовищі Linux
- •1. Команди роботи з командним інтерпретатором ос unix
- •2. Створення програми
- •3. Функції введення-виведення.
- •4. Приклад програми
- •5. Основні керуючі конструкції мови с
- •6. Індівідуальні завдання
- •Лабораторна робота № 2. Автоматизація пакетних завдань
- •1. Компіляція багатомодульною програми
- •2. Автоматизація пакетних завдань
- •4. Завдання
- •Лабораторна робота № 3. Взаємодія програми з середовищем виконання
- •1. Аргументи командного рядка
- •2. Змінні оточення
- •3. Індівідуальні завдання
- •Лабораторна робота №4. Контроль виконання програми
- •1. Коди завершення програми
- •2. Функції обробки значення errno
- •3. Функція atexit()
- •4. Макрос asssert()
- •5. Індівідуальні завдання
- •Лабораторна робота №5 Файлові api.
- •1 Основні поняття
- •2. Права доступу до файлів
- •3. Інтерфейси для файлового введення / виводу
- •4. Системні виклики роботи з файлами
- •5. Індівідуальні завдання
- •Варіанти завдань
- •Лабораторна робота №6 Робота з каталогами та посиланнями
- •Методичні вказівки
- •1. Створення та видалення каталогу
- •2. Читання каталогу
- •3. Зміна каталогу
- •4. Управління жорсткими посиланнями
- •5. Управління символічними посиланнями
- •6. Перейменування файлів і каталогів
- •7. Індівідуальні завдання
- •Лабораторна робота №7. Одержання і відображення метаданих файлу.
- •Методичні вказівки
- •1. Механізми управління файлами ос unix
- •2. Отримання даних індексного дескриптору
- •3. Додаткові функції маніпулювання даними індексних дескрипторів
- •4. Отримання даних про відкриті файли
- •5. Індівідуальні завдання
- •Лабораторна робота №8. Керування процесами
- •Методичні вказівки
- •1. Загальні поняття
- •2. Створення поцесу
- •4. Перезавантаження програми процесу
- •5. Завершення виконання процесу
- •6. Системні виклики wait, waitpid
- •7. Індівідуальні завдання
- •Лабораторна робота №9. Використання каналів
- •Методичні вказівки
- •1. Заганьні відомості
- •2. Використання каналів
- •3. Індівідуальні завдання
- •Варіанти завдань
- •Лабораторна робота №10 Використання повідомлень
- •Методичні вказівки
- •1. Загальні відомості
- •2. Використання повідомлень
- •3. Індівідуальні завдання
- •Література
- •Системне програмування Посібник до виконання лабораторних та самостійних робіт
- •65082, Одеса, вул. Дворянська, 1/3
4. Макрос asssert()
Розроблено методики програмування, що дозволяють виявляти помилки на ранніх стадіях і вирішувати проблеми, що виникають у ході виконання програми.
Найпростіший спосіб виявлення ненормальних ситуацій - стандартний макрос asssert() у мові С.
# Include <assert.h>
assert (expression, [error_string])
Його аргументом є логічне вираження.
Якщо
expression = TRUE програма триває
Якщо
expression = FALSE програма завершується і видає повідомлення про помилку з зазначенням вихідного файлу, номер рядка, а також тексту вираження, що призвів до помилки. При цьому розробнику надається вибір - остаточно перервати роботу програми (Abort), перемкнутися в вікно отладчика (Retry) або продовжити роботу (Ignore).
Assert реалізований як макрос, тому вираз expression не може містити текстових літералів.
Даний макрос корисний для включення діагностики у програми:
правильність аргументів функцій,
виконання вхідних і вихідних умов при виклику функцій.
наявність непередбачених повертаються значень.
Assert() зручний ще тим, що є документацією, яка описує роботу програми безпосередньо в її початковому тексті. Якщо програма містить рядок assert (умова), то будь-який, хто читає вихідний текст, буде знати, що в даній точці програми зазначена умова завжди повинно бути істинним. Якщо ж умова не виконується, то, очевидно, в програмі присутня помилка.
Макрос ASSERT відстежує програмні помилки лише в перевіреній версії програми (#define DEBUG - стоїть за умовчанням). Цей макрос не створює ніякого коду в остаточній версії. Якщо саме в остаточній версії потрібно оцінити вираз, замість ASSERT слід застосовувати макрос VERIFY.
Якщо програма компілюється як реліз (# define NDEBUG), препроцесор прибирає з тіла програми всі виклики макросу assert (). Це має сенс тільки тоді, коли продуктивність є вузьким місцем програми, причому макрос потрібно відключати лише в найбільш критичних файлах.
Визначення ndebug повинно бути перед включенням файлу assert.h, тоді оператори assert () будуть "закоментовані".
Оскільки макрос assert () може віддалятися препроцесором з програми, потрібно ретельно перевірити, чи не мають вираження з ним побічних ефектів. У них не слід викликати функції, присвоювати значення змінним і користуватися модифікуючими операторами типу + +.
Наприклад, нехай у циклі викликається функція funct (). У разі успішного виконання вона повертає 0, інакше - нульове значення. Якщо написати так:
for (i = 0; i <100; + + i)
assert (funct () == 0);
програма буде зупинятися при успішному виконанні функції.
Припустимо, програма перекомпілювати з макроконстантой NDEBUG. У результаті з програми будуть видалені всі макроси assert (), і функція funct () взагалі не буде викликано. Щоб уникнути цього необхідно використовувати наступний підхід:
for (i = 0; i <100; + + i)
{int status = do_something ();
assert (status ==
0);}
В якості додаткового параметра assert може приймати також повідомлення, яке треба надрукувати в разі спрацювання.
assert (fopen (sFile), "Couldn't open file \ n");
Поради щодо використання assert ().
1. Перевірки наявності порожніх покажчиків, наприклад, в списку аргументів функції. Повідомлення про помилку, що генерується рядком
{ assert (pointer! = NULL)}
Отримане повідомлення про помилку
Assertion 'pointer! = (Void *)O)'failed
більш інформативно, ніж повідомлення, що видається у відповідь на спробу розкриття порожнього покажчика:
Segmentation fault ( core dumped)
2. Перевіряйте значення параметрів функції. Наприклад, якщо у функції передбачається, що параметр foo має тільки позитивні значення, поставте наступну перевірку на самому початку тіла функції:
assert (foo> 0);
Це допоможе виявити випадки неправильного використання функції, а також дасть зрозуміти кожному, хто переглядає вихідний текст програми , що функція накладає обмеження на значення параметра.
3. Макрос assert () не слід застосовувати для перевірки даних, що вводяться користувачем. Звичайно, вхідні дані завжди потрібно перевіряти, але іншими способами. Макрос assert () призначений лише для внутрішніх перевірок.
Приклад
# include <assert.h>
# include <stdio.h>
char * string = "" / * порожній рядок * /
int value = 1;
main ()
{assert(value> 0);
printf ("Пройшли assert ( value> 0) \ n ");
assert (* string! = '0');}