Что делал после исправления багов?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Что делал после исправления багов?
Этот вопрос на soft skills и процессы. За 10+ лет выработал чёткий процесс post-mortem после исправления критических ошибок.
Мой процесс после исправления бага
1. Верификация исправления
Первый шаг — убедиться, что баг действительно исправлен:
// Пример: Memory leak в обработчике исключений
// До:
void processData(std::vector<int>& data) {
int* buffer = new int[1000];
// ...
if (error) {
throw std::runtime_error("Error"); // Утечка!
}
delete[] buffer;
}
// После исправления:
void processData(std::vector<int>& data) {
std::unique_ptr<int[]> buffer(new int[1000]);
// ...
if (error) {
throw std::runtime_error("Error"); // Память освобождена автоматически
}
}
Записываю с Valgrind/ASAN и проверяю, что утечка исчезла:
valgrind ./program --leak-check=full
# Результат: no leaks are possible
2. Написание regression тестов
Добавляю unit-тест, который воспроизводит баг:
#include <gtest/gtest.h>
#include "memory_handler.h"
TEST(MemoryTests, NoLeakOnException) {
EXPECT_NO_THROW({
std::vector<int> data = {1, 2, 3};
processData(data); // Должно выбросить исключение
});
// С ASAN проверяем нет утечек
// Скомпилировано с -fsanitize=address
}
TEST(MemoryTests, CorrectCleanupAfterError) {
MockLogger logger;
EXPECT_CALL(logger, logError).Times(1);
// Баг был в том, что при ошибке не закрывались файлы
FileHandler handler("/tmp/test.txt");
EXPECT_NO_THROW(handler.process()); // Исключение обработано
// Проверяем, что файл закрыт
EXPECT_FALSE(handler.isOpen());
}
Пробегаю с ASAN:
make test ASAN_OPTIONS="detect_leaks=1"
3. Анализ root cause
Важно понять ЧЕМ было вызвано:
- Недостаточное тестирование? → Нужны unit-тесты
- Неправильное использование API? → Документация/code review
- Архитектурная проблема? → Рефакторинг
- Race condition? → Mutexes/atomics
Пример документирования:
// FIXME: BUG #1234 - Memory leak in exception handler
// Root cause: Raw pointer без RAII
// Решение: Использовать std::unique_ptr
// Прошло тестирование: 2026-03-15
std::unique_ptr<Buffer> buf(new Buffer(1000));
4. Code review и знание проблемы всей командой
Обязательно делюсь информацией:
# В commit message:
git commit -m "Fix: Memory leak in processData() - use unique_ptr
This fixes issue #1234. The bug was caused by raw pointer without
RAII. When exception was thrown, memory wasn't freed.
Solution: Wrapped raw pointer with std::unique_ptr.
Verified with AddressSanitizer: no leaks detected.
Added regression test: MemoryTests::NoLeakOnException
Reviewers: @john, @jane
"
Пост в Slack/Teams:
🐛 Fixed: Memory leak in FileHandler
Context: Bug #1234
Severity: High (production)
Service affected: DataProcessor
Root cause: Raw pointer without RAII pattern
Solution: Use std::unique_ptr with automatic cleanup
Verification:
✓ AddressSanitizer (no leaks)
✓ Regression test added
✓ Code reviewed
Docs updated: https://wiki.company.com/...
5. Обновление документации
Обновляю или добавляю документацию:
# Memory Management Guidelines
## Common Pitfall: Exception Safety
Bad:
```cpp
int* buffer = new int[1000];
if (error) throw std::runtime_error("error"); // Leak!
delete[] buffer;
Good:
auto buffer = std::make_unique<int[]>(1000);
if (error) throw std::runtime_error("error"); // No leak
See: Bug #1234
### 6. Обновление static analysis правил (если нужно)
```bash
# Добавляю в clang-tidy конфиг:
Checks: "-*,
modernize-use-unique-ptr, # Флаг raw pointers
clang-analyzer-unix.MallocWithoutFree,"
Проверяю, что static analysis ловит такие проблемы:
clang-tidy program.cpp -- -I.
7. Post-mortem встреча (для критичных багов)
Если баг попал в production:
- Когда произошёл — timeline
- Какой был impact — сколько пользователей затронуто
- Почему не поймали — анализ testing coverage
- Как это исправить в процессе:
- Улучшить unit-тесты
- Добавить integration-тесты
- Усилить code review
- Настроить CI/CD pipeline
8. Мониторинг и алерты
Добавляю мониторинг памяти в production:
#include "prometheus/client.h"
class MemoryGuard {
public:
MemoryGuard() {
initial_memory = getMemoryUsage();
}
~MemoryGuard() {
long final_memory = getMemoryUsage();
if (final_memory > initial_memory + THRESHOLD) {
memory_leak_counter.inc();
logger.warn("Possible memory leak detected");
}
}
private:
long initial_memory;
static const long THRESHOLD = 10 * 1024 * 1024; // 10 MB
};
9. Профилактика в будущем
Обновляю guidelines:
- Никогда raw new/delete, только make_unique/make_shared
- Всегда оборачивать RAII
- Обязательны exception-safety гарантии
- Статический анализ на каждом commit
Типичный timeline после исправления
Day 1:
├─ Исправить баг
├─ Добавить regression test
├─ Code review
└─ Merge to main
Day 2:
├─ Написать post-mortem (если production)
├─ Обновить документацию
└─ Обновить static analysis rules
Day 3:
├─ Встреча с командой
├─ Обсудить процессы
└─ Планировать улучшения
Weekly:
└─ Проверить, что улучшения работают
Главное правило
Баг — это возможность улучшить процесс, а не просто закрыть issue. Каждый баг, особенно критический, должен:
- Быть задокументирован
- Стать основой для regression теста
- Привести к улучшениям в процессе
- Быть известен всей команде