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

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

Менеджер: @Spiral_Yuri

РКН: https://clck.ru/3Foc4d
Download Telegram
Аллокатор памяти в NGINX по сути представляет собой указатель, который движется только вперёд.
В нём нет free list-ов, он избегает фрагментации и сохраняет минимальные накладные расходы на каждое выделение памяти.

Память выделяется из одного большого блока по мере поступления запросов.

Когда обработка запроса завершается, весь пул памяти освобождается целиком за один раз.
Именно этот аллокатор используется в nginx/src/core/ngx_palloc.c

👉 @Cpportal
Please open Telegram to view this post
VIEW IN TELEGRAM
10👍2
Я читал исходники SQLite и нашёл интересную вещь.

DELETE на самом деле не уменьшает размер файла базы данных.

Удалённые страницы попадают во внутренний freelist прямо внутри файла.

Новые INSERT сначала переиспользуют эти свободные страницы, а уже потом снова увеличивают базу.

Сам файл уменьшается только после VACUUM.

Можно удалить всё из базы на 1 ГБ, а файл всё равно останется 1 ГБ, пока вы его не сожмёте.

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

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

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