﻿# PVS\-Studio и проверка Loki

В PVS\-Studio 3\.10 будет существенно улучшена поддержка сложных конструкций, основанных на шаблонах, что позволяет эффективно искать ошибки даже в коде тех программ, где используются сложные шаблонные библиотеки, такие как Loki\. Но начнем по порядку\.

Не так давно, когда наш продукт для проверки 64\-битного кода назывался Viva64, к нам обратился администратор открытой библиотеки Loki\*, с предложением проверить, как хорошо она совместима с [64\-битными](https://pvs-studio.ru/ru/blog/terms/0001/) Windows\-системами\. В этот момент для Windows эта библиотека существовала только в 32\-битном варианте\. Мы согласились, и, затаив дыхание, приступили к этой задаче\. Дело в том, что разработчики компиляторов часто используют библиотеку Loki как эталонный тест, позволяющий определить совместимость со стандартом языка Си\+\+\. В ней используются весьма сложные конструкции языка Си\+\+\. Мы не были уверены, что успешно сможем ее проанализировать\. Мы считаем большим достижением, что наш анализатор не завис на ней, не завершился с критической ошибкой и смог выдать осмысленную диагностику\.

Однако результаты диагностики показали существенный недостаток анализатора Viva64\. Дело в том, что Viva64 не умеет инстанцировать шаблоны и не может найти в них многие ошибки\. Приведем поясняющий пример:

```cpp
01 template <class T, class M>
02 class TemplateClass
03 {
04 public:
05   char m_char;
06   T *m_t;
07   M m_m;
08   T Get(int index) { return m_t[index]; }
09   void Set(int value) { m_t[m_m] = value; }
10 };
11
12 TemplateClass <char, int> A;
```

В этом коде обнаруживалась только одна потенциальная ошибка в 8 строке\. В этой строке в качестве индекса массива используется переменная типа int, что потенциально опасно при работе с большими массивами данных\. При диагностике этой ошибку не имеет значения, что является типом T\. А вот две другие ошибки, о которых будет сказано ниже, анализатор Viva64 не обнаружит\. Можно сказать, что анализатор Viva64 проверяет код шаблонов достаточно поверхностно и диагностирует только те ошибки, которые в нем присутствуют в независимости, с какими аргументами будет инстанцирован шаблон\.

Данный недостаток имеет свои корни в библиотеке OpenCxx, на основе которой была создана библиотека VivaCore, являющаяся основой анализатора Viva64\. Причина очень проста \- OpenCxx просто не умеет инстанцировать шаблоны\. Это смотрится достаточно странно, так как это весьма ограничивает возможности применения библиотеки\. Есть правда подозрение, что поддержка инстанцирования шаблонов в библиотеке OpenCxx существовала, но затем была специально удалена, прежде чем проект стал открытым и общедоступным\. Об этом косвенно свидетельствуют какие\-то странные заглушки и непонятные полупустые классы, связанные с обработкой шаблонов\.

Мы давно знали об этом недостатке и его последствиях для диагностики, но именно библиотека Loki подтолкнула нас заняться реализацией механизма для проверки инстанцированных шаблонов\. Мы создали механизм, который инстанцирует шаблон и вновь анализирует его, основываясь на новых знаниях о типах\. Реализация пока не идеальна и требует усовершенствования, но позволяет выявить множество новых ошибок\. Рассмотрим это на основе примера, представленного выше\.

После реализации механизма инстанцирования, анализатор сообщил нам уже о трех диагностических сообщениях:

Строка 3: error V401: Instantiate TemplateClass < char , int \>: The structure's size can be decreased via changing the fields' order\. The size can be reduced from 24 to 16 bytes\.

Строка 8: error V108: Incorrect index type for "m\_t"\. Use memsize type instead\.

Строка 9: error V108: Instantiate TemplateClass < char , int \>: Incorrect index type for "m\_t"\. Use memsize type instead\.

Встретив в коде строку "TemplateClass A <char, int\> A;" анализатор инстанцировал данный шаблон и произвел анализ, уже имея информацию о типах T и M\. В результате он сообщил, что структура данных в классе неоптимальна \(V401\) и размер этого класса на 64\-битной системе может быть уменьшен с 24, до 16 байт\. Для этого необходимо переупорядочить члены класса\. Обратите внимания, что данная диагностика возможна только при знании, какой тип имеют члены\. Ведь предупреждения может и не быть, если, скажем, член m\_m будут иметь тип [size\_t](https://pvs-studio.ru/ru/blog/terms/0044/)\. В этом случае переупорядочевание полей не поможет уменьшить размер класса\.

Ошибка в строке 8 диагностируется как и раньше, так как знание о типах T и M здесь не имеет здесь значения\.

Последняя ошибка в строке 9 также связанна с индексацией массива с использованием переменной типа int\. Здесь информация о типе M уже играет важную роль и используется анализатором при работе\.

Внесенные усовершенствования дали возможность значительно полнее проверить библиотеку Loki\. Более подробно об этой проделанной работе можно будет познакомиться в статье "64\-bit Loki", над которой сейчас идет совместная работа нашей команды и администратора библиотеки Rich Sposato\.

Анализ Loki мы осуществляли специальной исследовательской версией Viva64\. Но теперь решили интегрировать новые возможности в состав новой версии PVS\-Studio 3\.10 \*\*, которая выйдет в ближайшее время\. Пользователям будет доступна новая опция DoTemplateInstantiate, которая включит режим глубокого анализа шаблонов\.

**\*Примечание\. Библиотека Loki** для языка программирования C\+\+ написана Андреем Александреску как часть книги "Современное проектирование на С\+\+: Обобщенное программирование и прикладные шаблоны проектирования"\. Библиотека построена на шаблонном метапрограммировании и активно использует возможности языка C\+\+ для обобщённого программирования\. \([Wikipedia\. Loki\.](https://ru.wikipedia.org/wiki/Loki)\)

**\*\*Примечание\.** **PVS\-Studio** \- программный продукт, объединивший в себе и расширивший возможности статических анализаторов Viva64 и VivaMP\. Нумерация PVS\-Studio была начата с версии 3\.00, чтобы подчеркнуть, что это эволюционное развитие уже имеющихся инструментов\. В версии 3\.00 мы не стали спешить с поддержкой инстанцирования шаблонов, а решили реализовать эту возможность в PVS\-Studio 3\.10\.