У березні 2024 року ОНЦД Білого дому США опублікував рекомендацію, в якій радить розробникам уникати програмування на C і C++ через їхню вразливість до критичних проблем безпеки. У рекомендаціях пропонувалося перейти на більш безпечні мови, як Rust, що викликало жваву дискусію в програмістській спільноті.
Особисто я не згоден з твердженням, що C++ inherently (за замовчуванням) небезпечний. Правильне використання таких технік, як RAII, smart pointers (розумні вказівники) та інші сучасні практики можуть зробити C++ міцним та безпечним.
Джерело зображення
Однак написання безпечного коду на C++ вимагає значних навичок і досвіду — якості, яких не завжди дотримуються всі розробники.
C++ не є єдиним інструментом з великою потужністю — навіть така електризуюча і, здавалося б, небезпечна річ, як вогонь, має бути під контролем. Як вогонь чи електрика можуть одночасно освітлювати і знищувати, так і C++ надає розробникам величезну потужність для створення високопродуктивних системних додатків, але ця потужність вимагає дисципліни та поваги.
У словах Дядька Бена з Spider-Man: "З великою силою приходить велика відповідальність." Ця відповідальність полягає в дотриманні кращих практик, розумінні підводних каменів мови і прийнятті нових інновацій, як ініціатива Safe C++.
Саме тут вступає в гру Safe C++ Alliance. Альянс запровадив ініціативу з модернізації мови, надаючи розробникам інструменти та практики для підвищення безпеки без шкоди для продуктивності.
Що таке “Safe C++”?
Safe C++ — це відповідь на довготривалі вразливості в розробці на C++, зокрема в управлінні пам'яттю, відстеженні тривалості життя об'єктів та багатозадачності. Впроваджуючи нові інструменти, перевірки безпеки та практики, Safe C++ намагається зробити мову безпечнішою та легшою для використання розробниками, які створюють безпечні та високопродуктивні додатки.
Основні особливості
1. Автоматична перевірка меж
Safe C++ забезпечує перевірку меж для масивів і контейнерів, таких як std::vector
. Доступи до меж, які виходять за допустимі межі, фіксуються на етапі компіляції, що усуває одне з основних джерел помилок.
std::vector vec = {1, 2, 3};
vec[5] = 4; // Помилка: доступ до елемента за межами масиву
2. Управління тривалістю життя та перевірка позичок
Натхненний Rust, Safe C++ реалізує відстеження тривалості життя, щоб запобігти проблемам, таким як висячі вказівники, використання після звільнення пам'яті та подвійне видалення.
int* ptr = new int(10);
delete ptr;
// Компілятор відстежує володіння та запобігає використанню ptr після видалення.
3. Безпечніша багатозадачність з синхронізацією потоків
Safe C++ гарантує безпечний доступ до спільних ресурсів за допомогою механізмів, таких як std::mutex
та std::lock_guard
.
#include
#include
std::mutex mtx;
int shared_data = 0;
void safe_increment()
{
std::lock_guard lock(mtx);
shared_data++;
}
cpp
`std::span` для безпечніших операцій з масивами
`std::span` пропонує безпечніший спосіб роботи з масивами, забезпечуючи перевірку меж і спрощуючи операції.
void process_array(std::span
{
for (int& value : data)
{
value *= 2;
}
}
```
Кращі практики для написання безпечного C++
Навіть до впровадження Safe C++ розробники на C++ могли застосовувати низку кращих практик для підвищення безпеки коду:
- RAII: Автоматичне керування ресурсами, такими як пам'ять, дескриптори файлів і сокети.
- Розумні вказівники (Smart Pointers): Заміна сирих вказівників на
std::unique_ptr
іstd::shared_ptr
, щоб запобігти витокам пам'яті. - Константна коректність (Const Correctness): Використання
const
для оголошення незмінних змінних, що робить код більш зрозумілим. - Інструменти статичного аналізу: Використання інструментів, таких як Clang-Tidy і санітайзери на зразок AddressSanitizer, для виявлення потенційних проблем на ранніх етапах.
- Valgrind: Виявлення витоків пам'яті та недійсних доступів до пам'яті для забезпечення безпечного та ефективного коду.
Потрібен час
Хоча Safe C++ пропонує революційні функції, його впровадження потребуватиме часу. Ініціатива все ще знаходиться на стадії проекту і має бути схвалена комітетом стандартів C++. Після цього постачальники компіляторів, такі як GCC, Clang і MSVC, повинні будуть реалізувати ці зміни, що може зайняти роки.
Крім того, адаптація існуючих кодових баз до використання можливостей Safe C++ буде складною, що обмежує раннє впровадження переважно новими проектами. Тим часом розробники можуть звернутися до альтернатив, таких як Rust, який уже пропонує вбудовані гарантії безпеки.
Чому ці зміни важливі
Safe C++ вирішує критичні уразливості, такі як безпека пам'яті, переповнення буферів і умови гонки — проблеми, які часто використовуються зловмисниками. Переміщення виявлення помилок із часу виконання в час компіляції зменшує ризики безпеки і робить системи більш надійними.
Наприклад:
- Перевірка меж запобігає переповненням буфера.
- Відстеження тривалості життя усуває висячі вказівники.
- Перевірка позичок забезпечує безпечний і синхронізований доступ до спільних ресурсів.
Ці зміни не тільки забезпечують безпеку критичних систем, але й зменшують витрати на налагодження та обслуговування.
Шлях вперед
Хоча Safe C++ не вирішить усі проблеми одразу, він є важливим кроком уперед у забезпеченні безпеки мови. Розробники можуть продовжувати використовувати кращі практики, одночасно впроваджуючи можливості Safe C++ по мірі їхнього появи. У довгостроковій перспективі Safe C++ забезпечує, щоб C++ залишався актуальним і конкурентоспроможним у світі, орієнтованому на безпеку.
Що далі для C++?
Safe C++ — це більше, ніж технічне вдосконалення — це порятунок для однієї з найпотужніших і найбільш використовуваних мов програмування у світі. Усуваючи її історичні проблеми з безпекою, Safe C++ пропонує шлях для розробників створювати безпечні високопродуктивні додатки без відмови від екосистеми, в яку вони інвестували. Зі змінами, що впроваджуються, очевидно, що C++ має потенціал процвітати в майбутньому, де важливими є безпека та продуктивність.
З нетерпінням чекаємо на майбутнє C++, яке буде не лише швидшим, але й безпечнішим!
Перекладено з: Safe C++: How the U.S. White House Sparked a Revolution in Secure Programming