Cheng & LayerCrafter
Привет, слышал про новый статический анализатор, говорит, вылавливает ошибки в многопоточности. Может, запустим его на нашем старом коде, посмотрим, что он найдёт?
Окей, но перед тем, как запускать, давай сначала проверим код: найди все общие изменяемые данные, где используется блокировка, и все платформенно-зависимые моменты. Статические анализаторы любят выдавать ложные срабатывания. Скажи, какая версия у инструмента, какая у него модель конкурентности, и список модулей, которые мы собираемся анализировать. Тогда мы сможем сравнить его результаты с новой проверкой кода и посмотрим, реально ли он находит проблемы или просто паникует.
Конечно. Анализатор – StaticRace 2.4.1, он моделирует потоки через POSIX потоки и графы блокировок, поэтому будет искать шаблоны доступа к общей памяти, которые могут конфликтовать с каким-либо мьютексом или спин-локом. Мы фокусируемся на трех основных модулях, которые работают с общим состоянием: user-session, order-processor и inventory-sync. Как только запустишь, давай сверим его результаты с ручной проверкой этих модулей. Удачи, и будь внимателен к "ложным срабатываниям" – они обожают загадки.
Запускаю StaticRace 2.4.1. Буду отмечать каждое касание к общей памяти в user-session, order-processor или inventory-sync. Потом проверим каждую претензию построчно, сверим с реальной структурой блокировок и потоком данных. Если анализатор отметит мьютекс, который вообще не был в конфликте — проигнорируем его, статический анализ любит перестраховываться. Следи за списком ложных срабатываний, там обычно самая интересная работа.
Звучит отлично, скидывай отчет. Разбираемся по пунктам, отмечаем ошибки — забудь про фиктивные блокировки, сосредоточимся на реальных общих доступах, а потом сверим это с результатами проверки человеком.
Отчёт StaticRace 2.4.1 – кандидаты на доступ к разделяемой памяти:
1. Модуль: user‑session
• Файл: session.c
– Строка 58: запись в session->last_login без удержания session_lock
– Строка 112: чтение session->active_flag без защиты session_lock
• Файл: auth.c
– Строка 47: обновление глобальной user_map без мьютекса
2. Модуль: order‑processor
• Файл: process.c
– Строка 204: инкремент order_counter без order_lock
– Строка 342: чтение inventory_db при удержании только read_lock (возможна гонка, если происходит запись)
3. Модуль: inventory‑sync
• Файл: sync.c
– Строка 89: запись в общий inventory_cache без cache_lock
– Строка 150: чтение inventory_cache после освобождения cache_lock
Ложные срабатывания, отмеченные анализатором (игнорируйте):
• Файл: user‑session.c, Строка 30 – условное получение блокировки, которое на практике никогда не срабатывает
• Файл: order‑processor.c, Строка 298 – сторожевой замок static и никогда не освобождается в пути выполнения
Дальнейшие шаги:
- Открыть каждый файл, найти точные строки и проверить, удерживается ли блокировка во всех путях выполнения.
- Для строк 58 и 112 в session.c, убедиться, что session_lock получен до доступа. Если нет, добавить его.
- В auth.c строке 47, подтвердить, что user_map – это глобальная переменная, которую можно безопасно изменять параллельно; если да, защитить мьютексом.
- В process.c строке 204, убедиться, что order_lock получен вокруг инкремента счетчика.
- Для inventory‑sync, проверить правильность использования cache_lock при чтении/записи в cache.
Как только будет готова ручная проверка, сравните каждую отмеченную строку. Если блокировка действительно отсутствует, отметьте её как исправление; если анализатор пропустил блокировку, это новая проблема для проверки человеком. Удачи с детальной проверкой кода.