Для безопасной работы с памятью использована концепция защиты из языка NewLang, адаптированная для С++ и дополненная контролем инвалидации ссылочных типов. В основе безопасного управления динамической памятью лежит использование сильных и слабых указателей, а также контроль времени жизни копий переменных с сильными указателями во время компиляции исходного кода программы.
Предложенная техника защиты походит на концепцию владения и заимствования из языка Rust, но реализована на базе сильных и слабых ссылок (стандартных механизмов С++ shared_ptr и weak_ptr). Любые операции с данными для переменной по ссылке возможны только после её захвата, т.е. после преобразования слабой ссылки (weak_ptr) в сильную (shared_ptr).
Способ маркировки объектов в коде библиотеки реализован с помощью С++ атрибутов «[[memsafe(…)]]», что походит на способ из спецификаций P3038 и P3081 с профилями безопасности, опубликованных Бьёрном Страуструпом (Bjarne Stroustrup) и Гербом Саттером (Herb Sutter).
Пример работы плагина анализатора для кода:
std::vector‹int› vec(100000, 0); auto x = vec.begin(); auto y = vec.end(); vec = {}; vec.shrink_to_fit(); std::sort(x, y); // malloc(): unaligned tcache chunk detected or Segmentation fault
Командная строка для запуска компилятора с плагином:
clang++ -std=c++20 -Xclang -load -Xclang ./memsafe_clang.so -Xclang -add-plugin -Xclang memsafe _example.cpp
Фрагмент вывода плагина компилятора с сообщениями об ошибках, связанных с недействительностью ссылочных переменных после изменения данных в основной переменной:
_example.cpp:29:17: warning: using main variable 'vect' 29 | vect = {}; | ^ _example.cpp:30:17: warning: using main variable 'vect' 30 | vect.shrink_to_fit(); | ^ _example.cpp:31:27: error: Using the dependent variable 'beg' after changing the main variable 'vect'! 31 | std::sort(beg, vect.end()); // malloc(): unaligned tcache chunk detected or Segmentation fault | ^
Уровень сообщений плагина можно ограничить в коде с помощью макроса или аргументом командной строки. После проверки исходного кода, плагин можно вообще не использовать, так как он только анализирует AST, но не вносит в него никаких исправлений. С использованием пространства имён «memsafe» и разделением защищённого и незащищённого (unsafe) кода можно познакомиться в данном примере.
Источник: http://www.opennet.ru/opennews/art.shtml?num=62830