Макрос 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");