Valgrind: перевірка та відлагодження програм

Витік памяті (Memory Leak) – це процес неконтрольованого зменшення оперативної памяті, повязаний помилками в працюючих програмах які не звільняють більше не потрібні ділянки пам’яті. Найчастіше витоки памяті трапляються у мовах програмування, де програміст має доступ до ручного управління пам’яттю(C/C++). Для пошуку помилок при роботі з пам’ятю існують різні інструменти, в цій статті буде розглянутий один із них – Valgrind.

from: www.welovebug.com

Valgrind – інструмент призначений для виявлення витоків памяті та її помилок, працює під Linux. Ця програма дозволяє виявити неініціалізовану пам’ять, запис в память за межі масиву (мова С не контролює цього), випадки коли виділена память не звільняється(память яка більше не використовується,але зашилається зарезервованою).

Використані наступні  програмні інструменти:

  1. Sublime Text 2 – зручний текстовий редактор з підсвідкою синтаксису;
  2. Valgrind – 3.10.1;
  3. Ubuntu Linux 12.04 (LTS).

Останню версію Valgrind можна завантажити із офіційного сайту. Для встановлення потрібно розпакувати архів, і перейти в папку. після цього виконати команди для встановлення:

./configure
make
sudo make install

 Пошук помилок та витоків памяті:

Ця програма виділяє  динамічній пам’яті місце під  масив із 20 елементів int типу, записує значення в масив, виводить повідомлення “ОК”. Ця програма містить 2 помилки, але вона компілюється без жодних зауважень. Збережемо цю програму під іменем arr.c

скомпілюаємо програму командою:

gcc arr.c -o arr

та запустимо на виконання:

./arr

Результатом виконання буде “ok” повідомлення. На перший погляд здається що все працює вірно,але це не так. Для перевірки програми використаємо інструмент Valgrind, запустивши його командою:

valgrind –leak-check=full ./arr

детальніше про команди valgrind можна прочитати тут. Після цього відобразиться результат перевірки:

Як видно із звіту, ми маємо 80 байт витоку памяті (20 * sizeof(int) = 20 * 4 = 80). Ця проблема виникла тому, що пам’ять була виділена, але не звільнена після роботи програми. Для більш детального звіту, добавимо ключ -v і запустимо перевірку знову:

valgrind –leak-check=full  -v ./arr

Ми виділили в динамічній пам’яті 20 елементів, тобто data[20], і можемо звертатись до цієї памяті  через індекс

від data[0] до data[19],

або через вказівник *data (назва масива, це його нульовий елемент) до *(data + 19) 

При більш детальному звіті видно що ми записуємо значення після виділеного блоку тобто в data[20] , в область пам’яті яка не належить програмі, а може використовуватись іншими програмами, що може призвести до пошкодження даних, чи аварійної ситуації у випадку якщо по цій адресі( яку пошкодила наша програма) знаходились значення наприклад критичного рівня тиску чи температури.

Виправимо програму змінивши індекс масива в який записуємо значення, добавимо функцію звільнення пам’яті (free()), перекомпілюємо її (gcc arr.c -o arr )

Виправлена програма

та знову протестуємо її:

valgrind –leak-check=full  -v ./arr

Як видно, зараз витоки пам’яті та помилки відсутні.

Більш детально ознайомитись з Valgrind можна в цьому відео:

C/C++ дозволяє повний доступ до пам’яті – що відкриває великі можливості, але водночас покладає велику відповідальність на програміста. Навіть така невелика програма може містити помилки, які можуть стати причиною пошкодшення чи втрати даних.