Обновить
128K+

C++ *

Типизированный язык программирования

181,67
Рейтинг
Сначала показывать
Порог рейтинга
Уровень сложности

range-for перестал ронять программу на временном объекте, зато теперь дольше держит мьютекс

Уровень сложностиСредний
Время на прочтение9 мин
Охват и читатели3.3K

range-based for в C++ выглядит безопасным местом, пока в него не попадает временный объект с внутренней ссылкой. Такой код может годами работать в продакшене, а затем начать читать освобождённую память после смены компилятора или настроек сборки. В статье разбирается, как C++23 изменил время жизни временных объектов в таких циклах, почему поддержка стандарта зависит от компилятора и какие проверки помогут найти проблемные места в кодовой базе.

Узнать детали

Новости

BLDC и магнитный энкодер — рецепт получения позиционного привода из FPV-моторчика

Уровень сложностиСредний
Время на прочтение5 мин
Охват и читатели3.8K

Эксперимент: а можно ли собрать достаточно точный привод из старого FPV-мотора, чтобы в дальнейшем использовать при создании, к примеру, робота-манипулятора или подвеса камеры.

Читать далее

Обработка цифрового звука фильтрами

Уровень сложностиСредний
Время на прочтение25 мин
Охват и читатели5.5K

В данном материале в максимально простой форме изложены основы обработки цифрового звука, без подробного погружения в теорию цифровой обработки сигналов. Прилагается готовый код на C++ для расчета цифровых фильтров и собственно обработки звука.

Читать далее

Lock‑free по нарастающей

Уровень сложностиСложный
Время на прочтение16 мин
Охват и читатели9.8K

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

В качестве панацеи предлагают lock-free структуры, но и тут полно ловушек — банальный регулярный вызов ядра SetEvent способен сжечь весь выигрыш от lock-free. Сами алгоритмы lock-free порой тяжеловесны, не всегда предлагают удачный trade-off и даже не всегда уместны. Но что ещё хуже: будучи применёнными без должной тщательности, они могут не только не дать выигрыша, но даже навредить.

В этой статье мы разберём устройство нескольких базовых объектов библиотеки wxl и познакомимся с концепцией «алгоритм дешевеет под нагрузкой». Мы пройдём путь от трёх базовых инструкций процессора до готового канала, разберём, как продление release-последовательности спасает от ABA, как ленивые триггеры arm/disarm позволяют будить поток только тогда, когда он реально спит, и как заставить данные летать между ядрами без обращений к операционной системе.

Готовы? Приступаем...

Симулятор микропроцессоров: запускаем BASIC и не только

Уровень сложностиСредний
Время на прочтение28 мин
Охват и читатели9.4K

Со времени написания последней статьи я продолжал работу над I8086 и практически закончил его реализацию, но было бы странно приходить с материалом типа “я добавил поддержку еще одного процессора”. Я решил основательно подготовиться к этой публикации.

Читать далее

Эволюция эксплуатации переполнения буфера в Windows: от Stack Smashing до ROP и CET

Уровень сложностиСредний
Время на прочтение19 мин
Охват и читатели6.7K

Как менялась эксплуатация переполнений буфера в Windows за последние десятилетия?

Рассмотрим путь от классического Stack Smashing до современных механизмов защиты потока выполнения. На практике рассматриваются x86-техники переписывания EIP, NOP-sled, JMP ESP, эксплуатация SEH, переход к ROP как способу обхода DEP.

Практически продемонстрированы примеры создания и эксплуатации указанных уязвимостей.

Читать далее

Производительность сетевых бэкендов в Linux

Уровень сложностиСредний
Время на прочтение39 мин
Охват и читатели5.4K

Сколько на самом деле стоит путь пакета через ядро Linux, и сколько из этой стоимости снимают io_uring, AF_XDP и DPDK? Собрал библиотеку, в которой один и тот же цикл отправки и приёма работает поверх семи разных путей, и прогнал её на двух очень разных стендах: на домашнем десктопе с двумя 10-гигабитными портами сетевой карты Intel 82599, соединёнными AOC-кабелем, и на паре инстансов AWS c6in.4xlarge.

Читать далее

Как ускорить асинхронные генераторы в CPython на 40%, выкинув скрытые исключения

Уровень сложностиСредний
Время на прочтение3 мин
Охват и читатели5.1K

Недавно я гонял бенчмарки на свежей сборке CPython (ветка с tail-call интерпретатором, PGO + LTO, GCC) и снял флеймграф стандартного бенчмарка async_generators из набора pyperformance (рекурсивный обход дерева на 100 000 нод с глубиной вложенности ~17).

Картина на профиле оказалась фееричной: почти треть всего процессорного времени (29%) сжиралась кодом, который вообще не делал никакой полезной работы.

Рантайм создавал, настраивал, а затем тут же уничтожал объекты исключений StopIteration, о существовании которых Python-код даже не догадывался.

Ниже о том, откуда растут ноги у этой проблемы в Си-коде CPython и как пара правок в genobject.c дали ускорение в 1.33x — 1.53x.

Углубиться в кишки CPython

Small String Optimization: где заканчивается стек и начинается куча

Уровень сложностиПростой
Время на прочтение3 мин
Охват и читатели7.2K

При написании одного парсинга, в цикле которого создается std::string заметил одну странность, что при определенных ключах цикл работает заметно дольше. Оказалось, дело в инициализации std::string. Написал на это дело бенчмарк.

Читать далее

Код, пот и слезы: композиционный анализ проектов на С/С++

Уровень сложностиСложный
Время на прочтение14 мин
Охват и читатели10K

В экосистемах со сложившейся моделью пакетных индексов вроде Python, Java или JavaScript состав проекта обычно начинают анализировать с манифеста, где разработчик перечисляет прямые зависимости проекта и их допустимые версии. Менеджер пакетов читает эти требования, выбирает совместимые версии и подтягивает зависимости, которые нужны самим пакетам. Конкретный результат выбора сохраняется в lock-файле, где фиксируется уже не диапазон, а точные версии прямых и транзитивных зависимостей. В результате получается список всех пакетов, необходимых для работы с проектом.

В проектах на C и C++ такой общей записи, как правило, нет. Одну библиотеку могут устанавливать через менеджер системных пакетов, другую собирать из исходников в отдельном пайплайне, третью копировать прямо в каталог с исходным кодом проекта. Все они могут оказаться в рабочем приложении, хотя ни один источник не обязан перечислять их все в одном месте.

На крупной кодовой базе это быстро становится проблемой. Например, в нашем разборе автоматизации SBOM для LibreOffice в проекте была сотня с лишним C/C++ библиотек, собственная сборочная система и ресурсы вроде шрифтов и словарей, которые тоже попадают в поставку. За каждым компонентом такого SBOM стоит отдельное расследование от файла и команды сборки к имени проекта, версии и источнику. На каждом переходе теряется своя часть данных.

В CodeScoring мы анализируем состав программных продуктов и на практике часто сталкиваемся с ограничениями разных экосистем. Разбор проектов на C/C++ требует особого внимания. В этой статье мы разобрали особенности этой экосистемы, которые осложняют построение SBOM, и постарались рассказать, что позволяют выяснить разные методы анализа.

Читать далее

Миллионы объектов со стабильными адресами, или как удержать состояние под строгим RT дедлайном цикла

Уровень сложностиПростой
Время на прочтение25 мин
Охват и читатели5.6K

Рассмотрим класс задач, который встречается в разных областях. Долгоживущий процесс держит состояние из нескольких миллионов объектов по 2 КБ каждый. На это состояние напрямую указывают и другие потоки, в том числе внешние, и заменить эти указатели копированием или доступом через менеджер не позволяет сама архитектура. Например, потокам интерфейса с аппаратной частью нужно читать данные в реальном времени, без какой‑либо синхронизации с главным потоком. Рядом крутится цикл обработки событий, и его итерация обязана завершаться за десять миллисекунд. Это строгий RT дедлайн.

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

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

Решения взяты из реального проекта, библиотеки‑ядра libgsml3parser для построения программной GSM/2G базовой станции. Там роль объекта играет сессия абонента, а 3GPP правила задают конкретные таймеры. Оба решения переносятся на любую систему того же класса ограничений почти без изменений.

Читать далее

Telegram Desktop под атакой прокси: деанонимизация, утечка секретов и RCE с правами SYSTEM

Уровень сложностиСложный
Время на прочтение32 мин
Охват и читатели8.6K

Многие пользователи в России подключают Telegram через прокси, чтобы сохранять доступ к информации. Но что, если сам прокси окажется враждебным?

Мы обнаружили, что такой сервер мог без предупреждения получить доменные данные Windows, раскрыть личность пользователя и многократно извлекать фрагменты памяти Telegram Desktop. В лаборатории в этих фрагментах оказывались тестовые пароли, API-ключи и другие секреты из повторно используемых буферов.

В корпоративной Windows-среде атака могла пойти дальше: перехватить NTLM-аутентификацию и через AD CS привести к удалённому выполнению кода с правами SYSTEM. В статье — исходный код, PoC и полная цепочка атаки.

Читать далее

Держи хотпас в холоде, а кеш в тепле

Уровень сложностиПростой
Время на прочтение37 мин
Охват и читатели12K

В литературе по оптимизации, работа с памятью стоит не на первом месте, и даже если вы добрались до этих глав там, с большой вероятностью будут рассказывать про пропускную способность, чтобы система могла перемалывать условные пять ГБ/с вместо трех. И в целом это правильная метрика, когда у вас потоковая обработка, или батчи данных вродя запекания освещения, сборки навмеша, или компиляция шейдеров. Там имеет значение сколько данных прошло через процессор за отведённое время, и все стандартные приёмы (SoA, плотные массивы, линейный обход, векторизация) работают на эту метрику.

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

В играх, особенно разных стратегиях, симуляторах и факторингах, потоковая задача прогнать через кеш как можно больше данных остро не стоит, зато вылезают разные latency-задачи, которым нужно, чтобы данные этих задач из кеша по возможности не выкидывали, а работая в группе по возможности избегать кешканибализма и драки за шину.

Читать далее

Ближайшие события

Кросс-компиляция под андроид и не только

Уровень сложностиСредний
Время на прочтение18 мин
Охват и читатели7.4K

Сегодня широко используют cmake add_subdirectory и сборку через Gradle для кросс-компиляции сишных библиотек под андроид. Мы же рассмотрим более продвинутый и универсальный способ, который работает со множеством систем сборки и позволяет любым проектам найти свои зависимости без написания отдельных костылей под каждый проект: будем отдельно собирать каждую библиотеку ее собственной системой сборки в общий $PREFIX

Читать далее

Корутины C++: как приручить асинхронный I/O

Уровень сложностиСложный
Время на прочтение23 мин
Охват и читатели9.7K

Когда комитет стандартизации проектировал корутины, за кадром остался один неловкий момент: фрейм корутины (coroutine frame) — это динамический объект. Локальные переменные, буферы под чтение, аргументы и состояние автомата с точкой останова co_await должны где-то физически лежать, и по умолчанию компилятор выделяет это пространство из общей кучи через глобальный operator new. В асинхронном GUI, где корутина заводится на каждое нажатие клавиши и на каждое чтение из файла, это означает межпоточные блокировки кучи на каждом шаге с потенциальным переключением контекста — ровно то, от чего корутины обещали избавить.

И это не единственный сюрприз: сам по себе co_await асинхронности не даёт. Учебный awaitable запускает работу только в момент ожидания, и две асинхронные операции подряд на деле не запускаются асинхронно - идут с холостым кругом между ними; чтобы корутины стали по-настоящему асинхронными, механизм запуска операции пришлось отделить от того, что даёт язык. Эти вещи неочевидны, о них почти не пишут, и тем, кто присматривается к корутинам, стоит смотреть на них в первую очередь.

Заглянуть под капот

Откуда берётся сложность

Уровень сложностиПростой
Время на прочтение10 мин
Охват и читатели23K

Похоже что тема сложности и грязи в играх нашла отклик у читателей Хабра, и @andz даже пообещал поставить тысячу плюсов если бы мог, так что ловите вторую часть, которая должна была быть в части первой, но её там не было.

В основе любого инженерного искусства лежит великая иллюзия контроля над хаосом и открывая пустой файл, мы искренне верим, что в этот раз архитектура точно‑точно останется кристально чистой. Никто в здравом уме не пишет сложный код ради удовольствия (хотя нет, пару человек я все‑таки знаю, но это скорее исключение из правил), и если вы открыли систему частиц и увидели там хардкод для каждой платформы, то это, скорее всего, программисту, писавшему эту систему, выдали число, мало времени и сказали сделать красиво «читобыработало», но читобыработало — не всегда красиво, красиво — не всегда быстро, быстро — не всегда работает.

Число... например, 16 мс или 33 мс или 8 гигабайт, из которых 5 доступны, или «игра должна показать первый интерактивный кадр не позже чем через десять секунд после запуска, иначе сертификацию не пройдем». Как только у свойства системы появляется измеримая цель, простота перестаёт быть бесплатной и превращается в то, чем вы платите.

Читать далее

Частичное применение в C++: владение, время жизни и категории значений

Уровень сложностиСредний
Время на прочтение22 мин
Охват и читатели10K

Носителям прекрасного языка программирования C++ тема частичного применения может показаться скучной. Что примечательного в пяти строчках кода? Но дьявол кроется в деталях: я часто встречал реализации, которые работали не так, как ожидали их авторы. Иногда дело доходило до undefined behavior. Поэтому здесь хочется разобраться прежде всего с владением, временем жизни и категориями значений.

Разобраться в деталях

YOLO‑JSON: Рефлексия + #embed + JSON schema = сверхоптимизированный парсер

Уровень сложностиСредний
Время на прочтение6 мин
Охват и читатели9.4K

В прошлой статье я представил свою библиотеку для парсинга JSON. Краткое содержание - мы используем новые инструменты стандарта С++26 (в основном, рефлексию) для автоматической генерации оптимизированных парсеров для конкретных JSON, что позволило нам обогнать simdjson в несколько раз.

Здесь мы рассмотрим, как можно генерировать целевые структуры для объектов JSON напрямую из JSON схем при помощи других трюков из стандарта 26.

Читать далее

Выбираем бэкенд в 2026 (PHP, Dart и C++ Drogon)

Уровень сложностиСредний
Время на прочтение8 мин
Охват и читатели13K

Поехали.

Вообще говоря, я всегда делал бэкенд исключительно на PHP. Я считаю его отличным языком для бэкенда, вернее не только для бэкенда, а отличным языком. Некоторые не любят PHP за малый порог вхождения. Типа через этот малый порог вхождения входит очень много непрограммистов, которые потом пишут говнокод. Но я придерживаюсь мнения, что PHP никак не виноват в этом. Скорее наоборот. На PHP логика просыпается даже у тех, кто кроме говнокода ничего написать не может. Поэтому в любом случае это отличный язык программирования, который каждый год хоронят, но никак похоронить не могут. И в 2026 году он живее всех живых и показывает отличные результаты.

Вторым в списке для сравнения я решил поставить Дарт. Дело в том, что самое узкое место применения Дарта — это как раз-таки применение на серверах. Потому что в мобильной разработке он уже как стандарт, веб, фронтенд мало-мальцевски он тоже подтягивает. Но вот на серверах пока что его используют очень мало. Одна из причин на то, что его мало используют на серверах, — это отсутствие библиотек, таких как, например, есть у PHP. Но, тем не менее, это совсем не значит, а тем более сейчас в эпоху LLM, это совсем не значит, что Дарт негоден на серверах. Как покажет сравнение, он очень-таки годен.

Третий кандидат для сравнения — это C++. Это его фреймворк Drogon, который в каком-то там 2014 или 2015 годах взлетел как самый быстрый фреймворк для серверов на бэкенде по скорости. Если честно, я ни разу не писал бэкенд на C++, поэтому это была первая попытка. Просто хотелось посмотреть, как C++ уничтожит двух других оппонентов со своей 100x производительностью.

Читать далее

Грязные игры

Уровень сложностиПростой
Время на прочтение11 мин
Охват и читатели19K

Вы знаете, что игры бывают очень архитектурно «грязными» внутри? Но это не помешало им продаваться миллионами копий, или быть написаннами одним человеком на фреймворке для браузерок, или на Lua поверх библиотеки для геймджемов, или вообще ребенком в бесплатной версии юнити. При этом мощный кастомный движок с ECS, job‑системой, своим рендером и рефлексией повсюду вы тоже знаете, но игра на нем, скорее всего лежит третий год у вас в беклоге, так и не сыграная даже пару часов.

Попросили меня по старой дружбе, где‑то с полгода назад, помочь с разработкой и выводом игры в Steam. Ребята до этого занимались нефтью, и накопив деньжат, решили, что называется оставить след в индустрии. Если честно, я несколько отвык от такого «детского» кода и простых решений, что меня несколько удивило, хотя и вернуло на грешную землю из объятий ентрепрайза. Но я сразу оговорюсь, что простая архитектура это не оправдание плохого кода, а способ выбрать, где именно вы позволяете себе быть сложным. Бюджет сложности конечен... прежде всего размером вашей натуральной оперативкой, и тратить его надо туда, где игрок это увидит.

Читать далее
1
23 ...