tgindex

Бестиарий программирования

описание

Наблюдения за жизнью ошибок в коде. Андрей Карпов. ГОСТ Р 71207-2024, ГОСТ Р 56939-2024, РБПО, Статический анализ кода Канал-дублёр в MAX: https://max.ru/join/3VWTp9apkQvTMSRQ__LGiTQ5NGVBj8p_tOpwlQO6vS8

1 137
подписчиков
Охват к подписчикам
36,7%
ERR
Реакции к просмотрам
0,98%
156 на 38 постов
Пересылки к просмотрам
0,30%
48
Постов в день
1,0
всего 38

Где отзываются чаще

доля реакций к просмотрам
  • 11 авг.Статья вне тренда: Помешательство вокруг ИИ парализовало принятие решений И некоторые комментарии хороши: Мне очень интересно наблюдать за людьми которые одновременно понимают, что нейрослоп не может написать сказку для детей так, чтобы на второй странице не потерять смысл. И при этом убежденны, что эта же конструкция способна давать советы по бизнесу или легко написать операционную систему.3,78%
  • 4 авг.Когда ИИ платят за строки кода :) static int ksys_read(int fd, char *buf, u32 len) { u32 i; char c; int pid = (int)ring3_current_pid; int slot; if (fd != 0 || !buf) { if (fd != 0 || !buf) { if (fd == 0) { return ERR_FAULT; } } } .... } Проверка эквивалентна if (!buf && fd == 0) return ERR_FAULT; и выглядит подозрительно. Но мне сейчас лень изучать код дальше. Просто поделился тем, что улыбнуло :)3,31%
  • 12 авг.SAST и DAST спешат на помощь (часть 3 из 3) При этом такую ошибку можно моментально обнаружить с помощью статического или динамического анализа. Статический анализатор PVS-Studio сразу предупреждает об аномалии в коде с помощью сообщения: V742 Function receives an address of a 'char' type variable instead of pointer to a buffer. Inspect the first argument. Или достаточно воспользоваться динамическим анализом. AddressSanitizer (gcc ключ: fsanitize=address). Он сразу покажет проблему уже на первом самом простом тесте Test1. Юнит-тесты и динамический анализ работают в паре. Санитайзер обнаруживает проблему на этапе запуска юнит-теста. Не будет теста — ошибка всплывёт гораздо позже. Заключение Статический и динамический анализ хорошо дополняют юнит-тесты и другие методы выявления ошибок. При этом нет какого-то лучшего метода или инструмента. Статические и динамические анализаторы имеют свои слабые стороны и дополняют друг друга. В свою очередь, юнит-тесты могут выявить ошибки в логике, где, скорее всего, будут бессильны анализаторы. Используйте всё. По началу это потребует вложений, но со временем окупит себя ранним выявлением большого процента багов на самых ранних этапах разработки. Чем раньше ошибка обнаружена, тем проще и дешевле её исправление (подход shift-left testing).2,76%
  • 18 июл.Кажется я превратился в тролля. Но автор заслужил :) Мой комментарий к статье "Операционная Система на C без знаний C". Я так понимаю, речь идёт об этом проекте OS. Мдя. Ну что же, автору предстоит узнать ещё много о языке С. Например, что такое выход за границу буфера. void terminal_write_hex(uint64_t hex_num) { uint64_t index_buffer = 0; char buffer[sizeof(uint64_t)]; if (hex_num == 0x0) { terminal_write("0x0"); return; } terminal_write("0x"); while (hex_num > 0) { uint64_t digit = hex_num % 16; if (digit >= 10) { digit = digit - 10; buffer[index_buffer] = 'A'+digit; }else { buffer[index_buffer] = '0' + digit; } hex_num = hex_num / 16; index_buffer++; } Какой милый баг. Посмотрите на размер буфера: не учитывается, что один байт превращается в два символа. Интересные времена "безопасного ПО" настают. Простите за едкость комментария, но не удержался, увидев проект автора: Safe Life System Наш проект — это платформа для обеспечения и сохранения безопасности информации в цифровой среде, а также для развития независимой IT-экосистемы. Мы создаём комплекс программного обеспечения, ориентированный на защиту данных, открытость технологий и поддержку русскоязычного IT-сообщества.2,62%
  • 10 авг.У нас еще одна крутая новость! Мы запускаем новый цикл вебинаров "Надёжность, качество, безопасность ПО: методология и инструменты" ⚡️ В предыдущем цикле вебинаров "Вокруг РБПО" мы рассмотрели 25 процессов из ГОСТ Р 56939—2024, направленных на создание безопасных программных решений. Теперь поговорим не только о безопасности, но и в целом о создании качественного и надёжного ПО. Вместе с экспертами из разных компаний мы поговорим про развитие DevSecOps практик, подходы к написанию качественного кода, вопросы регуляторики, ИИ, функциональную безопасность встраиваемого ПО, а также про инструменты композиционного, статического, динамического анализа. Первый вебинар "Методы защиты и обеспечения безопасности ПО" пройдет 12 августа в 15:00 🗓 - Александра Уварова (Developer Advocate, PVS-Studio) в своем докладе "Автоматизация процессов обеспечения безопасности" расскажет, как одновременно с ускорением разработки и поставки программного обеспечения должна развиваться безопасность. В рамках вебинара рассмотрим методы эффективной интеграции SAST-инструмента в DevSecOps-пайплайн, чтобы выявлять уязвимости на ранних этапах, снижать риски и повышать эффективность безопасной разработки. - Дьяков Алексей (Эксперт по монетизации и защите ПО, Guardant) в своем докладе "Защита ПО: от анализа угроз до выбора стратегии" расскажет, почему защита ПО — необходимость, а не опция. Рассмотрим модели угроз, способы защиты и оценим, что компания может сделать самостоятельно. Главное — честно сравним, когда выгоднее строить свое решение, а когда покупать готовое. Регистрация доступна по ссылке 🔗 📲Мы в MAX #вебинар2,25%
  • 16 июл.Я сижу со взглядом на две тысячи ярдов после прочтения статьи "Манифест программиста, использующего AI-кодинг-агента". Как говорится, то ли смеяться, то ли плакать. Ну на смех в паре мест меня пробило. К самой статье претензий нет: я потрясён тем, что вообще у кого-то возникла потребность в написании этого манифеста. Как быстро где-то в индустрии уровень разработки прошёл путь от обсуждения книг про написание качественного кода до режима "голова для того, чтобы туда кушать". Я пока сомневаюсь, что настолько всё плохо. Надеюсь, автор преувеличивает и иронизирует. А если нет? О, мой Дейкстра! Появился тикет. Программист копирует ссылку, передает ее AI-кодинг-агенту и через какое-то время получает готовый Pull Request. ... Перед изменением кода программист должен воспроизвести баг, понять условия его появления и увидеть фактический результат. Скажите, что я сплю. Если вайб-программист просто впихивает задачу, не воспроизводя баг, не разбираясь в сути и не проверяя результат правок... это вообще что? Если программист не запустил продукт и не проверил результат, задача не закончена. Если программист просто передал тикет AI, а потом передал его код ревьюеру и тестировщику, он не выполнил свою работу. Он просто переложил ее на следующих людей. База. Но ведь автор это всё написал зачем-то, а в комментариях всерьёз идёт обсуждение. Прошу прочитать эту статью, она небольшая. Интересно услышать ваши впечатления, мнения и комментарии. Хочется вынести из всего этого происходящего сюрреализма какие-то полезные выводы.2,21%
  • 8 окт. 2025 г.А теперь время хорошей новости! 🔥 Друзья, коллеги, Java-разработчики, приглашаем вас на наш митап — Карты, деньги, JVM! На митапе обсудим внутренности JVM и компилятора: разберём, как JVM оптимизирует динамические вызовы, чем MethodHandle лучше рефлексии, и как компилятор обрабатывает код — от фронтенда до практического применения. Вас ждут два интересных доклада от разработчиков PVS-Studio, нетворкинг и вкусная пицца ❤️ 🗓 30 октября 📍Санкт-Петербург + онлайн Подробное расписание и регистрация по ссылке 🔗 #мероприятия #митап #java1,96%
  • 14 июл.без подписи1,59%
  • 7 авг.Элегантность кода благодаря C++23 Продолжим разбирать приёмы рефакторинга и посмотрим, как std::ranges::views::enumerate помогает сделать код более элегантным. В заметке я рассматривал рефакторинг и оптимизацию кода за счёт объединения циклов. В итоге я остановился на следующем варианте кода: static TensorImpl make_contiguous_tensor(const std::vector<int64_t>& sizes) { auto q = sizes.size(); std::vector<int64_t> strides(q); int64_t acc = 1; int64_t ne = 1; for (auto sz : std::ranges::views::reverse(sizes)) { strides[--q] = acc; acc *= (sz == 0 ? 1 : sz); ne *= sz; } //.... } Его недостаток в том, что всё равно необходимо использовать переменную q для работы с контейнером strides. Как можно написать ещё лаконичнее, я не сообразил, но такой способ есть! После публикации мне подсказали про enumerate. Эта штука появилась в C++23, и я как-то её пропустил. Сложно уследить за всеми нововведениями C++. С помощью enumerate можно сразу перебирать и элементы, и их индексы: constexpr static auto v = {'A', 'B', 'C', 'D'}; for (auto const [index, letter] : std::views::enumerate(v)) std::cout << '(' << index << ':' << letter << ") "; Будет напечатано: (0:A) (1:B) (2:C) (3:D). Но нам нужен обратный порядок, и такой вариант не подходит: for (auto const [i, sz] : std::views::enumerate( std::ranges::views::reverse(sizes))) Этот цикл будет перебирать элементы с конца, а индексы — по возрастанию от 0. Можно сделать, чтобы значения i также шли в обратном порядке? Можно. Это делается с помощью std::views::enumerate(sizes) | std::views::reverse. В итоге можно сократить код ещё на одну строчку: static TensorImpl make_contiguous_tensor(const std::vector<int64_t>& sizes) { std::vector<int64_t> strides(sizes.size()); int64_t acc = 1; int64_t ne = 1; for (auto const [i, sz] : std::views::enumerate(sizes) | std::views::reverse) { strides[i] = acc; acc *= (sz == 0 ? 1 : sz); ne *= sz; } //.... } Нельзя назвать это большим достижением, но зато на практике применили одну из новых возможностей C++23. Что со скоростью кода? Замер показал, что в рамках погрешности его скорость не изменилось. Т.е. этот вариант работает так же, как вариант №2 — "Мой вариант одним циклом" (см. замер скорости работы). Это не удивительно, так как по сути код идентичен предыдущему.1,57%
  • 13 авг.Раздутый C++ код (часть 2 из 2) А вот другой пухлый код, где PVS-Studio выдаёт сразу три предупреждения: • V547 [CWE-570] Expression 'is_empty' is always false. tensor_bindings.cc 3007 • V547 [CWE-570] Expression 'print_size' is always false. tensor_bindings.cc 3015 • V547 [CWE-571] Expression '!parts.empty()' is always true. tensor_bindings.cc 3023 Код, на который выданы предупреждения, на первый взгляд умный, с массивом, с циклом... А если присмотреться — лабуда. bool is_empty = false; // handled above; always false here bool print_size = is_empty && (self.sizes().size() != 1); bool suppress_dtype_non_empty = (!is_empty) && (self.dtype() == ScalarType::Float32 || self.dtype() == ScalarType::Int64 || self.dtype() == ScalarType::Bool); bool print_dtype = !suppress_dtype_non_empty; if (is_empty) { // For empty tensors, only print dtype when dtype != default float32 print_dtype = (self.dtype() != ScalarType::Float32); } std::string out = "tensor("; out += body; std::vector<std::string> parts; if (print_size) { parts.push_back(std::string("size=") + format_sizes(self.sizes())); } if (print_dtype) { parts.push_back(std::string("dtype=") + dtype_name(self.dtype())); } // Always include device suffix for CUDA tensors parts.push_back(std::string("device='cuda:") + std::to_string((int)self.device().index) + "'"); if (!parts.empty()) { out += ", "; for (std::size_t i = 0; i < parts.size(); ++i) { if (i) out += ", "; out += parts[i]; } } out += ")"; return out; Если присмотреться получше, то всё это можно сократить в три раза: std::string out = "tensor(" + body + ", "; if (self.dtype() != ScalarType::Float32 && self.dtype() != ScalarType::Int64 && self.dtype() != ScalarType::Bool) { out += std::string("dtype=") + dtype_name(self.dtype()) + ", "; } out += "device='cuda:" + std::to_string((int)self.device().index) + "')"; return out; Вот что здесь интересно: если рассуждать об анализе исходного варианта, то вроде как ошибок не находится. Код сложный, правильно работает, выхода за границу массива нет. Почтение к ИИ. Когда же код схлопывается до своей сути, то понимаешь, что там и ошибаться то негде. Он просто написан длиннее. Не к чему тут относиться с почтением. Итого: нет в проекте никаких настоящих 100,000 строк С++ кода. Думаю, что если вынести дубликаты в функции и провести рефакторинг, количество кода сократится раз в 5. Проект на 20,000 строк кода — это баловство. Вот и вижу в нём не ошибки, а проблему раздутого кода и предупреждения анализатора про большое количество ложных/истинных условий и т.п.1,47%
  • 16 июл.Современная разработка начинается с правильных инструментов. Завершился курс «Инструментальные средства ЗОСРВ «Нейтрино». Слушатели познакомились с инструментами разработки, отладки, анализа и верификации ПО для Нейтрино. Особое внимание было уделено работе с комплектом разработчика, его интеграции со статического анализатора PVS-Studio, системой сборки, а также инструментами анализа системных событий. Это позволило участникам познакомиться с современными подходами к повышению качества и надёжности программного обеспечения. Все участники успешно прошли тестирование и получили удостоверения о повышении квалификации. Обучение продолжается. Следите за анонсами новых наборов и выбирайте курс, который поможет решить ваши профессиональные задачи. #Курсы1,47%
  • 11:02GuardConf 2026 12 ноября этого года в Москве пройдёт конференция GuardConf 2026, посвящённая разработке и защите софта. В этом году я состою в программном комитете, и мы с коллегами прямо сейчас собираем программу — на прошлой неделе открыли Call For Papers. Если есть практический опыт, которым хочется поделиться, можно податься с докладом на один из двух треков: • Инструменты разработчика: качество кода, инженерные практики, автоматизация, безопасность, Open Source, производительность, AI и другие инструменты. • Стратегия и управление: архитектура, технический долг, масштабирование систем и команд, процессы разработки, AI в инженерных процессах. Подробнее про конференцию можно прочитать на сайте, там же уже открыта форма регистрации. А по поводу спикерства можно написать мне напрямую. Увидимся в ноябре! 🎤 feelin1,32%