PLC Lint // статический анализ

Разбор реальных находок

5 багов, которые компилятор не ловит

Проект в CODESYS собирается без ошибок — и уезжает на объект с невызванным таймером, усечённой уставкой и делением на переменную, которая иногда ноль. Синтаксис валиден, поведение — нет. Вот что находит статический анализ там, где компилятор молчит.

8реальных экспортов котельных
62–86score из 100
~10 секот загрузки до отчёта
0строк сохранено на диск

Findings — по важности

uncalled-timer high · критично

Невызванный таймер

VAR
    Pause_nasos : TOF;
END_VAR

// .Q используется в логике пуска насоса…
IF NOT Pause_nasos.Q THEN Start_Pump(); END_IF
// …но сам блок нигде не вызван — таймер не тикает,
// Pause_nasos.Q навсегда в дефолте.
Компилятор: собирается PLC Lint: поймал

Блок объявлен и читается, но не вызывается — пауза между пусками не работает. Найдено на реальном проекте котельной.

real-to-time-mul medium · внимание

Усечённая уставка через REAL_TO_TIME

tPulse := REAL_TO_TIME(rSetpoint) * 10;
// REAL_TO_TIME трактует число как миллисекунды
// и режет дробь ДО умножения — уставка уехала в мусор.
Компилятор: собирается PLC Lint: поймал

Классика «переводил секунды в миллисекунды». Домножение уже не спасает — дробь потеряна на конвертации.

div-by-zero high · критично

Деление на переменную-ноль

rAvg := rSum / iCount;
// iCount при пустой выборке = 0 → рантайм-исключение
// на объекте, а не на стенде.
Компилятор: собирается PLC Lint: поймал

Линтер различает: делитель — литеральный 0, переменная, которая никогда не присваивается ненулём, или присваивается 0 без проверки <> 0. Типо-осознанно: обычное деление REAL он не трогает — давили ложняки специально.

unreachable-branch high · критично

Недостижимая ветвь IF/ELSIF

IF x >= 100 THEN
    Alarm_Low();
ELSIF x >= 120 THEN   // недостижимо: >=120 уже поймано выше
    Alarm_High();
END_IF
Компилятор: собирается PLC Lint: поймал

Порядок порогов перепутан — верхняя авария никогда не сработает. Правило сравнивает полный правый операнд, чтобы не путать это с нормальным гистерезисом (T + 0.02).

watchdog-disabled medium · внимание

Сторожевой таймер задачи отключён

<TaskSettings KindOfTask="Cyclic" Interval="t#10ms">
    <Watchdog Enabled="false" />   <!-- на ВСЕХ задачах -->
</TaskSettings>
Компилятор: собирается PLC Lint: поймал

Не баг сам по себе — но для критичного процесса зависший цикл никто не перезапустит. Стоит увидеть в сводке, а не узнать на объекте.

Это реальный отчёт, не макет

Настоящий вывод на синтетическом проекте с внесёнными багами. Тот же отчёт получишь на своём экспорте — score, важность, разбивка по правилам и каждая находка с конкретным фиксом.

PLC Lint report Открыть полный живой отчёт →

Что проверяет PLC Lint

29 проверок по коду, структуре и конфигурации. Часть того, что ловит:

Это выборка — все 29 правил с фиксами на GitHub.

Прогони свой экспорт — узнай свой score

Загрузи .xml из CODESYS (Project → Export PLCopenXML), TwinCAT3, WAGO или ОВЕН. Отчёт за 10 секунд. Бесплатно, без регистрации для первого анализа, код не сохраняется.

…или посмотри живой пример отчёта →