EnglishРусский Map

Антипаттерн сброса стека ошибок

title
Антипаттерн сброса стека ошибок
type
concept
summary
Подавление одной неудобной ошибки через полную очистку общего канала библиотеки, незаметно стирающее чужие ошибки
tags
software-quality, security, c
created
2026-07-21
updated
2026-07-21
lang
ru
source_updated
2026-07-21
translated
2026-09-01
translator
lllm/antigravity/gemini-3.7-flash-medium

Антипаттерн обработки ошибок, при котором код "избавляется" от неудобной ошибки, полностью очищая общий контекстный канал ошибок библиотеки. В результате сбрасывается не только та ошибка, которая мешала, но и все остальные ошибки в канале - включая оставленные несвязанным кодом и указывающие на реальные проблемы. Название происходит из статьи Юлиана Андреса Клоде (Julian Andres Klode) об OpenSSL (openssl-error-handling-pandemic), где таким каналом служит стек ошибок OpenSSL, а вызовом очистки - ERR_clear_error().

Как это выглядит

Необходимое условие - библиотека, которая накапливает ошибки в общем состоянии процесса или потока, а не возвращает их напрямую по месту вызова. Архетип такого подхода - стек ошибок в OpenSSL. Есть две формы:

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

Оба варианта превращают "где-то произошла ошибка" в "ошибок нет". В коде, критичном к безопасности, это худшее из возможных преобразований: весь смысл канала ошибок в том и состоит, чтобы не продолжать работу при необработанном сбое.

Почему это распространяется

Локально код выглядит корректным и избавляет от сиюминутного симптома, поэтому он проходит ревью и копируется дальше - вплоть до официальных руководств upstream-проектов. Более глубокая причина - расхождение ментальных моделей: разработчики воспринимают канал как ячейку для одной ошибки, хотя на самом деле это стек. Из-за этого "очистить ошибку" читается как "очистить мою ошибку", тогда как на деле это значит "очистить ошибки вообще всех". Это регулярный сбой на границах библиотек с неявным общим состоянием ошибок.

Корректный паттерн

Ограничивать контекст своих ошибок вместо глобальной очистки. В OpenSSL для этого предназначены ERR_set_mark() / ERR_pop_to_mark(): ставится метка, выполняются операции, затем происходит возврат к метке со снятием только своих ошибок, оставляя чужие нетронутыми. Общий принцип: никогда не сбрасывать канал ошибок, которым не владеешь целиком. Нужно исправлять или обрабатывать конкретную ошибку в месте её возникновения, а если подавление неизбежно - делать это точечно (по метке или коду), а не уничтожая весь канал.

Связанные страницы: openssl-error-handling-pandemic (исходный разбор) и тема "ревью не способно это поймать" в reviewing-ai-code / testing-heavy-no-review-workflow - это именно тот тонкий баг корректности, который ускользает от человека на ревью и требует взамен рандомизированного или дифференциального тестирования.