С/С++ Portal | Программирование
15.3K subscribers
1.33K photos
220 videos
26 files
916 links
Присоединяйтесь к нашему каналу и погрузитесь в мир для C/C++-разработчика

Сотрудничество, реклама: @devmangx

Менеджер: @Spiral_Yuri

РКН: https://clck.ru/3Foc4d
Download Telegram
Этот алгоритм подсчёта установленных битов был опубликован ещё в 1957 году.

Он считает все 64 бита параллельно с помощью арифметики над битовыми масками, вместо того чтобы проходить по каждому биту в цикле.

Когда инструкция POPCNT недоступна, ядро Linux использует ту же идею в функции __sw_hweight64.

👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥14🤯53🤔1🤣1
Только что наткнулся на довольно безумную штуку — Linux прямо в браузере.

✓ Без установки и настройки, всё работает через WebAssembly
✓ Из коробки доступны Python, C, C++, Vim, cURL и другие инструменты
✓ Есть доступ в интернет, так что можно ставить дополнительные пакеты

Потыкать можно здесь: webvm.io

Честно, не ожидал, что это будет работать настолько хорошо.

👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
9🔥6👎2
Забавный факт: решето Эратосфена позволяет найти все простые числа примерно до 8 миллионов, используя всего около 1 МБ памяти.

Один бит хранит информацию об одном числе, а внутренний цикл помечает составные числа с помощью битовых операций.

Этот же подход используется в генераторах простых чисел и при выборе размеров хеш-таблиц.

Если пост был полезен как и всегда - ставь like 🫢

👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
139🔥7😁3
Одна из самых недооценённых анонсированных на WWDC фич — Container Machines. Она позволяет запускать на Mac лёгкое и постоянное Linux-окружение, в котором домашний каталог пользователя и репозитории автоматически монтируются внутрь контейнера.

По сути, разработчики получают Linux-среду, тесно интегрированную с macOS, без необходимости вручную настраивать виртуальные машины или сложную инфраструктуру контейнеров.🍎🐧

https://github.com/apple/container/blob/main/docs/container-machine.md

👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
6
Бинарный поиск, который вы заучили, скорее всего реализован с ошибкой.
Джон Бентли опубликовал реализацию бинарного поиска в Programming Pearls после того, как доказал её корректность и протестировал.

Ошибка оставалась незамеченной почти 20 лет.
Позже Джошуа Блох обнаружил ту же самую ошибку в реализации бинарного поиска, которую написал для JDK.
Исследование 1988 года показало, что корректная реализация бинарного поиска была только в 5 из 20 учебников.
Ошибка проявляется только на массивах размером 2³⁰ элементов и больше.
Проблема возникает при вычислении середины диапазона.

mid = (low + high) / 2


На очень больших массивах такое выражение может вызвать переполнение.
Исправление простое:
mid = low + (high - low) / 2


В C переполнение приводит к выходу за границы массива с непредсказуемыми последствиями.
В Java это заканчивается исключением ArrayIndexOutOfBoundsException.
Та же ошибка затронула Merge Sort и множество других алгоритмов класса «разделяй и властвуй».

Эта ошибка была и в ядре Linux — в kallsyms.c.
Вегард Носсум исправил её, а Линус Торвальдс одобрил патч.

Исправление сводилось к замене:
mid = (low + high) / 2;

на:
mid = low + (high - low) / 2;


Джошуа Блох завершил свою статью фразой, которая остаётся актуальной и сегодня:
«Трудно правильно написать даже самый маленький фрагмент кода, а весь наш мир работает на больших и сложных программных системах».


👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
20🔥1🥱1
Этот обычный на вид C-код содержит серьёзную уязвимость: она может повредить память и привести к эксплуатации.

Такой паттерн находили в OpenSSH в 2002 году, libtiff и куче других проектов.

Сможете сказать, в чём проблема, если код запускается на 32-битной системе?

Именно этот кусок кода стал причиной уязвимости OpenSSH (CVE-2002-0640).

nresp = packet_get_int();

if (nresp > 0) {
response = xmalloc(nresp * sizeof(char *));

for (i = 0; i < nresp; i++)
response[i] = packet_get_string(NULL);
}

Через неё атакующие могли ломать кучу, выполнять свой код на сервере и получать над ним контроль.


👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
👍105👀2
PID'ы переиспользуются. pidfd — нет.

Если вызвать kill() для PID, который ты сохранил 20 минут назад, есть шанс отправить сигнал уже совершенно другому процессу.
pidfd — это стабильный дескриптор конкретного процесса. Он остаётся привязанным именно к нему, даже если его PID позже будет переиспользован системой.

Одна из тех фич Linux, после знакомства с которыми возникает только один вопрос: почему я не знал об этом раньше?

👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
11🔥4
В исходниках Nginx HTTP-парсер реализован как ручная конечная машина с примерно 25 состояниями.
Каждый байт запроса обрабатывается по одному, с одной трансформацией состояния за символ.
Весь HTTP/1.1 request line проходит через этот парсер в один проход, без промежуточных буферизаций или повторного анализа.

Это классический подход для высокопроизводительных C-серверов: минимальные аллокации, предсказуемое поведение и высокая скорость.

👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
13👍3🔥3
Один геймер превратил GTA Online с 6-минутной загрузкой в игру с секундной загрузкой за один уикенд.
Rockstar терпел эту проблему почти 7 лет.

t0st разобрал игру на уровне реверса и выявил два узких места:
Один парсер каждый шаг вызывал strlen() на оставшихся 10 МБ JSON, повторяя лишнюю работу.
Другая функция делала почти 2 миллиарда проверок дубликатов на 63 000 уникальных предметов, хотя в этом не было необходимости.

// bug 1 - ChakraCore sscanf implementation
// github.com/chakra-core/ChakraCore/blob/master/pal/src/safecrt/sscanf.c

int sscanf(const char *string, const char *format, ...) {
size_t count = strlen(string); // scans the whole string before parsing starts

return input_s_l(..., string, count, ...);
}

// bug 2 - from t0st's decompilation notes

char __fastcall netcat_insert_dedupe(
uint64_t catalog,
uint64_t *key,
uint64_t *item
) {
uint64_t not_a_hashmap = catalog + 88;

if (!(*(uint8_t(__fastcall**)(uint64_t*))(item + 48))(item))
return 0;

array_find_and_insert(not_a_hashmap, key, &item); // linear search on every insert
}


То же самое игра, те же данные — всего несколько строк кода решают разницу между минутами и секундами.

t0st решил проблему максимально просто:
Для парсера JSON он не переписывал весь движок, а просто «повесил» хук на strlen() и кешировал результат, чтобы не пересчитывать его каждый раз. Для проверки дубликатов он заметил, что элементы уже уникальные, и пропустил проверку полностью.

// fix 1 - cache strlen results for very large strings

size_t strlen_cacher(char *str) {
static char *start, *end;

if (start && str >= start && str <= end)
return end - str;

size_t len = __builtin_strlen(str);

if (len > 20000) {
start = str;
end = str + len;
}

return len;
}


// fix 2 - skip the duplicate lookup entirely

char __fastcall netcat_insert_dedupe_hooked(
uint64_t catalog,
uint64_t *key,
uint64_t *item
) {
uint64_t not_a_hashmap = catalog + 88;

if (!(*(uint8_t(__fastcall**)(uint64_t*))(item + 48))(item))
return 0;

netcat_insert_direct(not_a_hashmap, key, &item); // bypass the scan
}


В итоге загрузка GTA Online упала с ~6 минут до менее чем 2 минут.
t0st позже сказал, что исправление выглядело как задача, которую один разработчик мог бы сделать меньше чем за день.
Rockstar выплатили ему $10,000 через программу bug bounty.

👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
33🔥6👍5😁1
В C есть оператор «идёт к», которого так и не добавили в стандарт.
Выглядит как оператор, но на самом деле им не является.

Компилятор интерпретирует его как:
(x--) > 0


Сначала выполняется постдекремент, затем результат сравнивается с нулём.

👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
🥱19👍125👎4🤔1
Стандартный макрос min(a, b) может вернуть неверный результат, если один аргумент знаковый (signed), а другой беззнаковый (unsigned).

Во время сравнения оба значения приводятся к unsigned, поэтому отрицательные числа превращаются в огромные положительные значения.

В ядре Linux макрос min() защищает от такой ошибки: он выполняет проверку типов и превращает подобные случаи в ошибку компиляции.

👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
😁108👍2
std::expected из C++23 может оказаться одним из самых практичных нововведений в языке за последние годы.
Он даёт структурированный способ обработки ошибок без использования исключений и выходных параметров.
Вызывающий код не может случайно проигнорировать возможность ошибки, при этом здесь нет управления потоком выполнения через исключения.

👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥193👍2👀1
Ещё одно распространённое заблуждение о C — многие думают, что строки обязательно нужно писать в кавычках. https://godbolt.org/z/qcWc4j3q3

#include <stdio.h>

#define puts(x...) puts(%:x)

int main() {
puts(Hello, world!);
}


👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
8🤔7👍2👀1
Предсказание ветвлений, переименование регистров, спекулятивное выполнение, буферы записи, трансляция μops.

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

Ты пишешь код под x86. Процессор переводит его во что-то другое и дальше работает уже с этим.

👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
10👎2🥱1💊1
В C++ появился новый оператор:

^^


В комитете его называют cat-ears operator («оператор кошачьих ушек»).
Именно через него в язык приходит рефлексия — одно из крупнейших изменений в C++ со времён появления шаблонов.

C++26 приносит в язык compile-time reflection (P2996).
Оператор ^^ позволяет превратить любую сущность — тип, функцию или элемент перечисления — в compile-time представление (mirror), которое можно анализировать и преобразовывать во время компиляции.

enum → строка? Одна функция.
JSON-сериализация? Без макросов, генераторов кода и километров шаблонов.
Автор предложения — Barry Revzin и ещё шесть соавторов.

https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2996r13.html
https://wg21.org/

👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
17👍6🤣4🥱1👀1
Если вы ещё не знакомы с этим, обязательно загляните в техническую и архитектурную документацию SQLite — там разобрано огромное количество впечатляющих инженерных деталей. Достаточно просто посмотреть на список тем, которые она охватывает.

[https://sqlite.org/docs.html]

👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
3🔥1
1. Введение в параллельные алгоритмы

https://www.cs.cmu.edu/~guyb/paralg/paralg/parallel.pdf

2. Один из лучших бесплатных курсов по низкоуровневой оптимизации производительности — курс Aalto University по программированию параллельных вычислений.

Внутри разбираются:

SIMD-векторизация
конвейеризация инструкций (instruction pipelining)
оптимизация работы с кэшем
параллельные алгоритмы
многопоточность
и другие техники повышения производительности

Если тебе интересно выжимать максимум из процессора и считать такты CPU, этот курс точно стоит пройти. https://ppc.cs.aalto.fi/


👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🤯1