Релиз проекта Memsafe для безопасной работы с памятью в С++

Опубликован релиз проекта Memsafe, реализующего механизм безопасной работы со ссылочными типами и динамической памятью в коде на языке С++. Защита может быть добавлена без нарушения обратной совместимости со старым С++ кодом. Проект оформлен в виде одного заголовочного файла memsafe.h и плагина для компилятора Clang. Код распространяется под лицензией LGPL 2.1.

Для безопасной работы с памятью использована концепция защиты из языка 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