64 біта для C + + програмістів: від / Wp64 до Viva64 (исходники), Різне, Програмування, статті

Розвиток ринку 64-бітних рішень поставило нові завдання в області їх верифікації і тестування. У статті йдеться про один з таких інструментів – Viva64. Це lint-подібний статичний аналізатор Сі / Сі + + коду, призначений спеціально для виявлення помилок, пов’язаних з особливостями 64 – бітних платформ. Висвітлено передумови для створення даного аналізатора і відображена його зв’язок з режимом “Detect 64-Bit Portability Issues” в Сі + + компіляторі Visual Studio 2005.


Один з найбільш частих питань, яке мені задавали розробники програм мовою Сі + +, навіщо потрібен аналізатор Viva64, якщо в Visual C++ 2005 існує вбудоване засіб діагностики коду, переносимого на 64-бітову архітектуру. Дана діагностика включається з використанням ключа компілятора /Wp64 і носить назву “Detect 64-Bit Portability Issues”. З відповідей на форумі і народилася ця стаття. У ній коротко розповідається про те, що послужило передумовою до створення статичного аналізатора Viva64 і в чому полягає його відмінність від ряду інших засобів верифікації та підвищення якості коду.


Ключ компілятора / Wp64 (Detect 64-Bit Portability Issues), безумовно, хороший засіб виявлення помилок, пов’язаних з перенесенням програми на 64-бітну систему. Він здатний вказати на багато місця в коді, які приведуть до некоректної роботи. Але тут криється тонкість. Багато широко поширені конструкції мови Сі + + потенційно небезпечні з точки зору 64-біт, але компілятор не може видавати на них попередження, так як в більшості випадків вони абсолютно коректні. Далі в прикладах цей аспект буде розкритий докладніше. Аналізатор Viva64 виробляє більш глибокий і детальний аналіз, виявляючи потенційно небезпечний код, і видає відповідну діагностику. Він не є аналогом або замінником / Wp64. Він є його розширенням і доповненням!


До випуску аналізатора Viva64 я брав участь у перенесенні досить великої програми на 64-бітну платформу, і виглядало це приблизно так. Перша пара днів пішла на те, щоб просто скомпілювати проект на новій архітектурі. Потім ще тиждень, на те щоб виправити всі небезпечні місця (точніше здавалося що все), які діагностували за допомогою ключів / W4 і / Wp64. В результаті через півтора тижні було отримано 64-бітний варіант програми. Весь вихідний код, за винятком сторонніх бібліотек, збирався з включеними опціями / W4 і / Wp64 без єдиного попередження. Варто також зауважити, що оскільки той проект розроблявся для декількох платформ, то, наприклад, під Linux він збирався компілятором gcc без попереджень з ключем-Wall. Наша команда була задоволена, і вважала, що перенесення майже завершений. Додаток робило вигляд, що працювало. Ми приступили до тестування.


І почалося … Помилки стали виявлятися в найнесподіваніших місцях. В результаті було витрачено більше двох місяців на налагодження і виправлення всіх знайдених помилок. Правки давалися насилу. Виявилося, що спеціалізованих програм, для пошуку даного класу помилок просто немає. Існуючі lint-подібні аналізатори коду допомогли дуже слабо і вимагали значних зусиль у налаштуванні.


Ви, напевно, запитаєте «А юніт-тести?» Вони повинні були звузити коло пошуку таких помилок. На жаль, проект існує багато років, і на ранніх етапах використання юніт-тестів не практикувалося. В результаті код покритий ними дуже фрагментарно. Але, на жаль, брак юніт-тестів для нашої ситуації проявився ось в чому. Тести не покривали ситуації обробки більше 4 гігабайт даних. Це зрозуміло, тому що раніше така обробка була просто неможлива. Та й зараз використання подібних тестів досить важко. Реалізація юніт-тестів для таких великих масивів даних призводить до величезних тимчасових витратах на їх виконання. Але як раз заради великих масивів і був початий перенесення на 64-бітну платформу.


Нічого не залишалося, окрім як тестувати і тестувати, аналізувати код очима і правити. Все це згодом і призвело до ідеї розробки спеціалізованого статичного аналізатора, заточеного спеціально на пошук помилок, що виникають при перенесенні Сі + + коду на 64-бітну платформу. Тепер розглянемо деякі ситуації, які дозволяє діагностувати аналізатор Viva64.


Приклад перший. Мій улюблений. Зміна поведінки віртуальних функцій. А проявитися він може дуже просто. Раптом у вас на 64-бітної платформі перестає працювати довідкова система в MFC додатку. Ось код, демонструє проблему.





class CWinApp {
virtualvoid WinHelp(DWORD_PTR dwData, UINT nCmd);
};class CMyApp : public CWinApp {
// Don”t called in x64 modevirtualvoid WinHelp(DWORD dwData, UINT nCmd);
};

У часи, Visual C + + 6 прототип віртуальної функції WinHelp мав в якості першого аргументу тип DWORD. І цілком логічно, що, перекриваючи цю функцію в той час, Ви теж використовували тип DWORD. Потім прототип функції в заголовних файлах Visual C + + помінявся, і перший аргумент став мати тип DWORD_PTR. На 32-бітної платформі все буде продовжувати працювати як і раніше. А от в 64-бітному режимі, немає. Це будуть просто дві різні функції і все. Ніхто не винен, а одну помилку ми вже знайшли.


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


Приклад другий. Вічні цикли.





size_t n = bigValue;for (unsigned i = 0; i != n; ++i) { … }

Ось приклад класичного вічного циклу, якщо змінна bigValue перевищить значення UINT_MAX. Компілятор навіть с / Wp64 змушений мовчати, так як це широко поширена операція порівняння двох змінних різної розрядності у бітах. Код зовсім коректний, при bigValue <= UINT_MAX. Але, створюючи 64-бітове додаток, ми часто маємо на увазі обробку великої кількості елементів. Тоді знайти і проаналізувати такі операції порівняння просто необхідно. Саме це і робить аналізатор Viva64. Він позначає всі операції порівняння 32-бітних типів, і типів, які на 64-бітної платформі стають 64-бітними.


Приклад третій. Некоректне явне приведення типу. Часто помилки обрізання 64-бітних типів до 32-бітових значень ховаються за явними привидами типів. Такі місця можуть існувати в коді за різними причин. Тут компілятор також не має прав видавати попередження. Одне і теж явне приведення типу можна записати безліччю способів:





size_t a;int b = (int)a;int b = (int)(a);int b = int(a);int b = static_cast<int>(a);

Пошук явних привидів типів, може стати досить трудомістким завданням. Тим більше що потрібно шукати не всі явні приведення, а тільки небезпечні з точки зору перенесення програми на нову платформу.


Тут знов може допомогти аналізатор Viva64, запушений у відповідному режимі пошуку.


Приклад четвертий. Некоректна індексація масивів.





size_t n = bigValue;unsigned index = 0;for (size_t i = 0; i != n; ++i)
array[index++] = 10;

На жаль, частою практикою програмування, є використання для індексації масивів типів int і unsigned. Більше ніколи так не робіть! Тільки ptrdiff_t і size_t! Якщо ви будите працювати з масивами, містять більше UINT_MAX елементів, як у прикладі, то робота алгоритму буде некоректна.


/ Wp64, на жаль знову не може допомогти. Якщо компілятор почне попереджати про індексацію по 32-бітному типу, то забракує пристойну частину вашого зовсім коректного коду. Адже помилка виникне тільки при роботі з величезними масивами, яких у вашій програмі може і не бути. Але, якщо у вас такі масиви є, то знайти подібні помилки досить складна задача.


Аналізатор Viva64 дозволяє Вам переглянути всі звернення в програмі до масиву по 32-бітовим індексам, і провести правки, якщо це необхідно. При цьому він досить інтелектуальний, щоб не показувати конструкції виду:





enum NUM { ZERO, ONE, TWO };
array[0] = array[ONE];

Хочеться запропонувати вашій увазі ще один спосіб відчути переваги Viva64. Уявіть, що у Вас є старий “брудний” код стороннього розробника. Він компілюється у Вас з відключеними попередженнями, так як правити його немає ніякого бажання або сенсу. Тепер уявіть, що Вам необхідно перенести цей код на 64-бітну платформу. Залишити вимкненими попередження – отримати непрацюючий 64-бітний код. Активізувати – зануритися на тижні чи місяці в їх перегляд. Ця реальна, але вельми сумна ситуація. Використовуючи Viva64, ви можете переглянути ТІЛЬКИ ТІ ділянки коду, які потенційно небезпечні в контексті підтримки 64 біт, не відволікаючись другорядними попередженнями. Це може істотно заощадити Ваш час.


Природно, це далеко не все, на що здатний аналізатор. Але я сподіваюся, що дав Вам загальне уявлення про нього. Упевнений, що він зможе заощадити комусь кілька мільйонів нервових клітин, дозволивши випустити 64-бітний продукт вчасно, а не як компанія з прикладу, із запізненням на два місяці.


Аналізатор є відмінним доповненням до інших засобів верифікації та підвищення якості додатку. Таким як, наприклад, / Wp64 в Visual Studio, статичний аналізатор PC-Lint від Gimpel Software або BoundsChecker від Compuware. Всі ці та багато інших інструментів можуть істотно полегшити життя програмісту і прискорити розробку програмного забезпечення. І сподіваюся, що Viva64 внесе в це свій істотний вклад.


Удачи в освоєнні 64-бітових систем!


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


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

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

Ваш отзыв

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

*

*