PrepBro
Профессии
PrepBro
Профессия:

Подготовка

  • Вопросы652
  • Задачи13

Аналитика

  • hh статистика
  • Анализ резюме

Практика

  • Тестовое собеседование
  • Mock-собеседование
  • Менторы

Поддержка / отзывы

Telegram админа
Профессия:

Подготовка

  • Вопросы652
  • Задачи13

Аналитика

  • hh статистика
  • Анализ резюме

Практика

  • Тестовое собеседование
  • Mock-собеседование
  • Менторы

Поддержка / отзывы

Telegram админа
Все 24 профессии
Android DeveloperData AnalystSystem Analyst1С DeveloperiOS DeveloperBusiness AnalystJava DeveloperData ScientistQA EngineerQA AutomationPHP BackendC/C++ BackendDevOps EngineerIT Project ManagerFrontend DeveloperNode.js BackendUnity DeveloperC# BackendProduct AnalystFlutter DeveloperPython DeveloperIT Product ManagerGo DeveloperData Engineer

© 2026 PrepBro. Все права защищены.

Telegram-бот

Вопросы по C/C++ Backend

Какие знаешь проблемы умных указателей?
2.2 Middle🔥 30💬 1

Проблемы и подвохи умных указателей

Умные указатели (smart pointers) — unique_ptr, shared_ptr, weak_ptr — это мощный инструмент для управления памятью в C++, но они имеют собственные проблемы и подводные камни, которые нужно знать.

Проблема 1: Циклические ссылки (circular references)

Это самая опасная проблема с shared_ptr — циклические ссылки приводят к утечкам памяти:

struct Node {
    int data;
    std::shared_ptr<Node> next;
    std::shared_ptr<Node> prev;  // ⚠️ Циклические ссылки!
};

// Утечка памяти
auto node1 = std::make_shared<Node>();
auto node2 = std::make_shared<Node>();

node1->next = node2;
node2->prev = node1;  // Циклическая ссылка!

// node1 и node2 имеют счётчики ссылок > 1
// Когда выходят из scope, не удаляются!
// Утечка: оба объекта живут вечно

Решение: использовать weak_ptr:

struct Node {
    int data;
    std::shared_ptr<Node> next;
    std::weak_ptr<Node> prev;  // ✅ weak_ptr не увеличивает счётчик
};
Читать полностью ->
Что такое ООП?
1.0 Junior🔥 30💬 1

Ключевое слово override в C++

Override — одно из самых важных ключевых слов в современном C++11+, которое спасает от множества ошибок при переопределении виртуальных функций.

Проблема до override

class Base {
public:
    virtual void process(int x);
    virtual void calculate();
};

class Derived : public Base {
public:
    // ОШИБКА 1: Опечатка в имени функции
    void proccess(int x); // Не переопределяет Base::process!
    
    // ОШИБКА 2: Неправильная сигнатура
    void calculate(double x); // Не переопределяет, создаёт новую!
    
    // ОШИБКА 3: Забыл const
    void process(int x) const; // Не переопределяет!
};

// Программист думает, что переопределил, но нет!
Base* ptr = new Derived();
ptr->process(5); // Вызовет Base::process, не Derived::process!

Решение: override

Читать полностью ->
Зачем нужен виртуальный деструктор?
1.0 Junior🔥 30💬 1

Зачем нужен виртуальный деструктор

Виртуальный деструктор — это критическое требование для полиморфных классов, обеспечивающее корректное удаление объектов через базовый указатель. Без него программа страдает от утечек памяти и корупции памяти.

Проблема: деструктор без virtual

Когда производный класс наследует базовый без virtual деструктора:

class Base {
public:
    ~Base() { std::cout << "Base destructor\n"; }
};

class Derived : public Base {
private:
    std::string buffer;  // Требует очистки
public:
    ~Derived() { 
        std::cout << "Derived destructor\n";
        // buffer автоматически очистится
    }
};

Base* ptr = new Derived();
delete ptr;  // ПРОБЛЕМА!

Что происходит:

  • Вызывается только ~Base()
  • Деструктор Derived() НЕ вызывается
  • Память buffer не освобождается
  • УТЕЧКА ПАМЯТИ

Решение: virtual деструктор

class Base {
public:
    virtual ~Base() { std::cout << "Base destructor\n"; }
};
Читать полностью ->
В чем разница между классом и структурой?
1.3 Junior🔥 30💬 1

Разница между классом и структурой в C++

В C++ различие между class и struct минимально, но стилистически и концептуально они используются по-разному.

Синтаксическое различие: Видимость по умолчанию

struct: public по умолчанию

struct Point {
    int x;              // ✅ public по умолчанию
    int y;              // ✅ public
    
    void move() {}      // ✅ public по умолчанию
};

Point p;
p.x = 10;            // ✅ OK — public
p.move();            // ✅ OK

class: private по умолчанию

class Point {
    int x;              // ❌ private по умолчанию
    int y;              // ❌ private
    
    void move() {}      // ❌ private по умолчанию
};

Point p;
p.x = 10;            // ❌ COMPILATION ERROR — private
p.move();            // ❌ COMPILATION ERROR — private

Наследование

struct Base { int x; };
struct Child : Base {};
// наследование PUBLIC по умолчанию
static_assert(std::is_same_v<decltype(Child().x), int>);  // ✅ x доступен
Читать полностью ->
Что такое RAII?
1.2 Junior🔥 30💬 1

RAII: Resource Acquisition Is Initialization

RAII — это фундаментальный паттерн в C++, который привязывает управление ресурсами к жизненному циклу объектов. Это одна из самых мощных инноваций языка, обеспечивающая безопасность памяти и надёжность.

Основная идея

Ресурсы захватываются в конструкторе, освобождаются в деструкторе.

Этот паттерн гарантирует:

  • Утечки памяти невозможны (деструктор вызовется ВСЕГДА)
  • Исключения обработаны правильно
  • Не нужно вручную отслеживать освобождение ресурсов

Базовый пример: File RAII

// ❌ БЕЗ RAII (C-style, опасно)
void process_file_bad() {
    FILE* f = fopen("data.txt", "r");
    
    // Если здесь исключение — файл не закроется!
    if (some_error_condition) {
        throw std::runtime_error("Oops!");
        // fclose(f) НИКОГДА не вызовется
    }
    
    // А что если раньше возвращаемся?
    if (file_empty) {
        return;  // утечка файлового дескриптора!
    }
    
    fclose(f);  // может быть, может не быть
}
Читать полностью ->
Расскажи о своём опыте
1.6 Junior🔥 30💬 1

Мой опыт разработки на C/C++

Обладаю более чем 10-летним опытом разработки высокопроизводительных backend-систем на C/C++. Специализирую на архитектуре масштабируемых приложений, где каждая деталь имеет значение.

Ключевые области знаний

Стандартная библиотека (STL)

Глубокое понимание контейнеров (vector, map, unordered_map, deque, list), алгоритмов и итераторов. Практический опыт оптимизации выбора структур данных в зависимости от паттернов доступа:

  • vector для последовательного доступа с минимальными выделениями
  • unordered_map для O(1) поиска с правильным хешированием
  • Использование move semantics и perfect forwarding для минимизации копирований

Управление памятью

Работал с разными подходами:

  • Ручное управление new/delete (legacy code)
  • smart pointers: unique_ptr для исключительного владения, shared_ptr для разделённого владения
  • RAII паттерн для гарантированного освобождения ресурсов
  • Отладка утечек памяти через Valgrind и AddressSanitizer
Читать полностью ->
Может ли конструктор быть шаблонной функцией?
1.7 Middle🔥 29💬 1

Конструкторы как шаблонные функции

Да, конструктор может быть шаблонной функцией (template constructor). Это мощный инструмент для написания обобщённого кода, позволяющий создавать объекты с различными типами данных через единый интерфейс.

1. Базовый пример

#include <iostream>
#include <type_traits>

template <typename T>
class Container {
private:
    T value;
    
public:
    // Обычный конструктор
    Container() : value() {}
    
    // Шаблонный конструктор
    template <typename U>
    Container(U val) : value(static_cast<T>(val)) {
        std::cout << "Template constructor called\n";
    }
};

int main() {
    Container<int> c1(42);           // int -> int
    Container<double> c2(3.14f);     // float -> double
    Container<std::string> c3("hello"); // const char* -> std::string
    
    return 0;
}

2. Шаблонный конструктор для конвертации типов

Читать полностью ->
Какой механизм может атомарно заблокировать два мьютекса?
1.6 Junior🔥 29💬 1

Атомарная блокировка двух мьютексов

Атомарная блокировка двух мьютексов — критическая проблема в многопоточном программировании, особенно для предотвращения deadlock ситуаций. Рассмотрим основные подходы и механизмы.

Проблема классического подхода

Если заблокировать мьютексы последовательно, возникает риск deadlock:

// Опасно!
mutex1.lock();    // Поток 1 берет mutex1
mutex2.lock();    // Может быть заблокирован

// Если другой поток имеет mutex2 и ждет mutex1 — deadlock

Решение 1: std::lock (C++11)

Самый надежный и рекомендуемый механизм:

#include <mutex>
#include <thread>

mutex mu1, mu2;

// Правильный способ
std::lock(mu1, mu2);  // Атомарно блокирует оба мьютекса
// Безопасная работа с защищенными ресурсами
mu1.unlock();
mu2.unlock();
Читать полностью ->
Каким образом можно создать файл только если его нет?
1.2 Junior🔥 29💬 1

Каким образом можно создать файл только если его нет?

В C++ есть несколько способов создать файл только если он не существует. Выбор зависит от платформы и требований.

1. POSIX: open() с флагами O_CREAT и O_EXCL

Это атомарная операция — либо создаёт файл, либо ошибка:

#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>

int createFileIfNotExists(const char* filename) {
    // O_CREAT: создать если не существует
    // O_EXCL: ошибка если существует
    // O_WRONLY: открыть на запись
    int fd = open(filename, O_CREAT | O_EXCL | O_WRONLY, 0644);
    
    if (fd == -1) {
        if (errno == EEXIST) {
            std::cerr << "File already exists\n";
        } else {
            perror("open failed");
        }
        return -1;
    }
    // fd содержит файловый дескриптор
    close(fd);
    return 0;
}

Преимущества: Атомарный, работает везде, низкий уровень.

Недостатки: Нужно проверять errno, низкоуровневый API.

2. C++17: std::filesystem

Читать полностью ->
Что требуется для использования структуры в качестве ключа unordered_map?
1.3 Junior🔥 29💬 1

Что требуется для использования структуры в качестве ключа unordered_map?

Использование пользовательских типов в качестве ключей в unordered_map требует специальной подготовки. Это частая задача при разработке backend-приложений, где нужны составные ключи (например, (user_id, date) или (source_ip, port)).

Основное требование: Hash функция

unordered_map использует хеширование вместо сравнения, поэтому нужно определить hash функцию для структуры:

#include <unordered_map>
#include <string>
#include <functional>

struct User {
    int id;
    std::string email;
};

// Вариант 1: Специализация std::hash
namespace std {
    template<>
    struct hash<User> {
        size_t operator()(const User& user) const {
            // Комбинируем хеши полей
            size_t h1 = hash<int>()(user.id);
            size_t h2 = hash<std::string>()(user.email);
            // Используем XOR и сдвиг (FNV-like)
            return h1 ^ (h2 << 1);
        }
    };
}
Читать полностью ->
Какие источники использовал для обучения?
1.0 Junior🔥 29💬 1

Источники использованные для обучения

За 10+ лет работы в C/C++ backend разработке я использовал разнообразные источники обучения, от классических книг до современных онлайн-ресурсов. Вот основные из них:

Классические книги

1. Effective C++ серия Скотта Мейерса

Это трёх-томная серия остаётся библией для C++ разработчиков:

  • Effective C++ (3rd Edition) — 55 практических советов по написанию лучшего кода
  • More Effective C++ — 35 более сложных техник
  • Effective STL — специализация на стандартной библиотеке

Эти книги учат не синтаксису, а философии и best practices. Каждый совет обоснован и показывает грубые ошибки, которые совершают даже опытные разработчики.

2. The C++ Programming Language Бьёрна Страуструпа

Официальный гайд от создателя C++. Массивный том, но содержит:

  • Полное описание стандарта
  • Обоснование дизайн-решений
  • Примеры и best practices
  • История развития языка

3. Modern C++ Design Андрея Александреску

Читать полностью ->
Какие знаешь особенности в процессе запуска ядра Linux?
3.0 Senior🔥 29💬 1

Особенности процесса запуска ядра Linux

Процесс загрузки ядра Linux — это критически важный этап, который должен понимать каждый системный программист и backend-разработчик, работающий с низкоуровневым кодом, оптимизацией систем и kernel-space приложениями.

Этапы загрузки ядра

1. BIOS/UEFI Phase

  • BIOS (Basic Input/Output System) или UEFI (Unified Extensible Firmware Interface) инициализируют оборудование
  • Выполняется Power-On Self Test (POST) — проверка памяти, дисков, процессора
  • Загружается bootloader (GRUB, LILO) с диска
  • BIOS/UEFI передаёт управление bootloader'у

2. Bootloader Phase

  • GRUB (Grand Unified Bootloader) — самый распространённый загрузчик
  • Читает конфигурацию из /boot/grub/grub.cfg
  • Загружает ядро Linux в память (обычно /boot/vmlinuz-*)
  • Загружает initramfs (initial ramdisk) — временную файловую систему в памяти
  • Передаёт управление ядру с параметрами командной строки
Читать полностью ->
Какая асимптотическая сложность удаления в vector?
2.0 Middle🔥 29💬 1

Какая асимптотическая сложность удаления в vector?

Краткий ответ

Удаление элемента из std::vector имеет сложность O(n) в худшем случае, где n — количество элементов в vector.

Почему именно O(n)?

std::vector — это динамический массив. Его элементы хранятся в памяти последовательно. Когда вы удаляете элемент, все элементы после него нужно сдвинуть на позицию влево, чтобы заполнить "дыру".

std::vector<int> vec = {10, 20, 30, 40, 50};
//                       0   1   2   3   4

// Удаление элемента на позиции 1 (значение 20)
vec.erase(vec.begin() + 1);

// Процесс:
// Было:    [10, 20, 30, 40, 50]
// Шаг 1:   Удаляем 20
// Шаг 2:   Сдвигаем 30 на позицию 1
// Шаг 3:   Сдвигаем 40 на позицию 2
// Шаг 4:   Сдвигаем 50 на позицию 3
// Итог:    [10, 30, 40, 50]

Количество операций сдвига: n - i - 1, где i — позиция удаляемого элемента и n — размер вектора.

Анализ разных случаев

Читать полностью ->
Почему уволился?
1.2 Junior🔥 29💬 1

Мой уход из последней должности

Отправляюсь из компании Yandex.Cloud по стратегическим причинам, а не из-за критических проблем.

Причины ухода

Необходимость более широкого опыта

В течение 5 лет работал глубоко в одной экосистеме — облачная инфраструктура и микросервисы. Организация отлично структурирована, но я достиг плато в части экспериментирования с новыми технологиями и подходами. Хотелось попробовать себя в:

  • Финтех и high-frequency trading (ultra-low latency)
  • Компилятор-ориентированная оптимизация
  • Распределённые базы данных
  • Game engine development

Стремление к лидерству

В текущей компании я был strong individual contributor (senior engineer), но не имел возможности влиять на архитектурные решения на уровне компании. Хочу присоединиться к команде, где я смогу:

  • Проектировать системы с нуля
  • Менторить junior разработчиков
  • Принимать архитектурные решения, влияющие на продукт
Читать полностью ->
Что нужно для работы с дескриптором в неблокируемом режиме?
2.0 Middle🔥 28💬 1

Что нужно для работы с дескриптором в неблокируемом режиме?

Для работы с файловым дескриптором (file descriptor) в неблокируемом (non-blocking) режиме необходимо выполнить несколько шагов и обработать особенности такой работы.

1. Установка флага O_NONBLOCK

Способ 1: При открытии файла/сокета

#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

// Открыть файл в неблокируемом режиме
int fd = open("file.txt", O_RDONLY | O_NONBLOCK);
if (fd == -1) {
    perror("open");
    return 1;
}

// Для сокетов
#include <sys/socket.h>
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
    perror("socket");
    return 1;
}

Способ 2: Установка флага на уже открытый дескриптор

#include <fcntl.h>
#include <unistd.h>

int fd = open("file.txt", O_RDONLY);

// Получить текущие флаги
int flags = fcntl(fd, F_GETFL);
if (flags == -1) {
    perror("fcntl F_GETFL");
    return 1;
}
Читать полностью ->
Со своей ли техникой нужно работать
1.0 Junior🔥 28💬 2

Со своей ли техникой нужно работать?

Краткий ответ

Нет, вы должны работать с компьютером компании. Это стандартная практика в IT-индустрии по соображениям безопасности, юридической ответственности и организационной логики. Однако есть исключения и нюансы, которые зависят от политики конкретной компании.

Почему компаниям нужна своя техника

1. Безопасность и контроль

  • Компания может контролировать софт, который установлен на рабочем компьютере
  • Регулярные обновления безопасности
  • Антивирусное ПО, защита от утечек данных (DLP)
  • Шифрование диска и защита от несанкционированного доступа
  • Логирование доступа к системе

2. Защита интеллектуальной собственности

  • Исходный код компании должен находиться только на корпоративном оборудовании
  • Легче отследить утечки данных
  • При увольнении просто конфискуют оборудование
  • На личном компьютере остаются следы кода (бэкапы, кэш)

3. Юридическая ответственность

Читать полностью ->
Можно ли ссылке присвоить другой адрес памяти?
2.0 Middle🔥 28💬 1

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

Ссылка связана с объектом навсегда

Когда вы инициализируете ссылку, она привязывается к конкретному объекту. После инициализации эта связь неразрывна:

int a = 10;
int b = 20;

int& ref = a;        // ссылка привязана к переменной a
// ref теперь всегда указывает на a

ref = b;             // ЭТО НЕ переприсваивает ссылку!
                     // Это присваивает значение b переменной a
                     // a становится равна 20, ref всё ещё указывает на a

cout << a << endl;   // выведет 20
cout << ref << endl; // выведет 20 (потому что это а)

Почему нельзя переприсвоить

Это архитектурное решение языка C++:

Читать полностью ->
Когда сложность поиска в бинарном дереве не логарифмическая?
2.0 Middle🔥 28💬 1

Сложность поиска в бинарном дереве поиска (BST) будет не логарифмической в следующих случаях:

1. Несбалансированное бинарное дерево (вырождение в список)

Когда дерево становится несбалансированным, оно может вырождаться в односвязный список. В худшем случае все элементы находятся только в правом (или только в левом) поддереве:

// Вырожденное дерево O(n)
struct TreeNode {
    int val;
    TreeNode* left;
    TreeNode* right;
};

// Пример вырождения: вставляем уже отсортированный массив
TreeNode* root = nullptr;
for (int x : {1, 2, 3, 4, 5}) {
    // Вставляем - получаем цепочку (right, right, right, ...)
}
// Поиск любого элемента требует O(n) операций

Это происходит когда:

  • Элементы вставляются в отсортированном порядке (возрастающем или убывающем)
  • Нет балансировки после вставок

2. Не является деревом поиска

Читать полностью ->
Какие плюсы и минусы многопоточности?
2.0 Middle🔥 28💬 1

Плюсы и минусы многопоточности в backend-разработке

Многопоточность — критический инструмент в современной backend-разработке, но она сложна и требует глубокого понимания. Давайте разберём обе стороны.

Плюсы многопоточности

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

Блокирующие операции — IO (сетевые запросы, работа с БД, файлы) требует времени. Многопоточность позволяет одному потоку ждать IO, пока другие обрабатывают вычисления или служат другим клиентам. Без потоков сервер будет в простое во время каждого запроса к БД.

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

Читать полностью ->
Чем отличается malloc от new в C++?
1.0 Junior🔥 28💬 2

Чем отличается malloc от new в C++?

malloc и new — это два разных способа динамического выделения памяти. Хотя оба выделяют память в heap, они работают по-разному и предназначены для разных целей.

Основные различия

Параметрmallocnew
ТипФункция CОператор C++
Заголовок<cstdlib>встроено в язык
Возвращаемое значениеvoid*Типизированный указатель
КонструкторыНЕ вызываетВызывает
ДеструкторыНЕ вызывает (free)Вызывает (delete)
ИнициализацияНетЕсть (в скобках)
Обработка ошибокВозвращает NULLВыбрасывает исключение
Пользовательская аллокацияНет (только в C++11+)Можно перегрузить
Memory pool / ArenaСложноЛегко (placement new)

1. malloc — выделение памяти без инициализации

Читать полностью ->
Что такое input/output?
1.0 Junior🔥 27💬 1

Input/Output (I/O) операции

Input/Output — это процесс обмена данными между программой и внешним миром (файловая система, сеть, консоль, устройства и т.д.). Это фундаментальная концепция в программировании и системном дизайне.

Определение

Input (Ввод) — получение данных из внешних источников:

  • Чтение файлов с диска
  • Получение данных по сети
  • Ввод данных с клавиатуры
  • Чтение с периферийных устройств (USB, sensors и т.д.)

Output (Вывод) — отправка данных во внешние места:

  • Запись в файлы
  • Отправка по сети
  • Вывод на экран (консоль)
  • Запись на печатающее устройство

1. I/O в C++ — Streams (потоки)

C++ использует концепцию streams (потоков) для абстракции I/O операций. Все I/O операции работают через специальные объекты.

Основные потоки:

#include <iostream>
#include <fstream>
Читать полностью ->
Что критично в новой работе?
1.0 Junior🔥 27💬 1

Что критично в новой работе для C/C++ Backend Developer

Выбор нового места работы — важное решение. Вот что я считаю критичным:

1. Технический стек и архитектура

Критично:

  • Современный C++ стандарт (как минимум C++17, лучше C++20)
  • Чистая архитектура — разделение слоев, SOLID принципы
  • Масштабируемость — система проектируется с мыслью о росте
  • Microservices или модульная структура — а не монолитный ад

Важно:

  • Какие технологии используются (Database, Message Queue, Cache)
  • Есть ли Code Review процесс
  • Есть ли нагрузочное тестирование и performance monitoring

Красный флаг:

  • C++98/C++03 код без плана на модернизацию
  • Полное отсутствие тестов
  • Хардкодные "волшебные числа" везде
  • Legacy код без документации

2. Команда и культура

Читать полностью ->
Какие знаешь принципы ООП?
1.6 Junior🔥 27💬 1

Принципы объектно-ориентированного программирования (ООП)

ОООП — парадигма программирования, основанная на концепции объектов, которые содержат данные (состояние) и методы (поведение). В C++ это реализуется через классы, структуры и наследование.

1. Инкапсуляция (Encapsulation)

Инкапсуляция — принцип скрытия внутренних деталей реализации и предоставления контролируемого интерфейса для взаимодействия. Это достигается через модификаторы доступа: private, protected, public.

class BankAccount {
private:
    double balance;  // скрыто от внешнего доступа
    
public:
    void deposit(double amount) {
        if (amount > 0) balance += amount;
    }
    
    double getBalance() const { return balance; }
};

Преимущества: защита инвариантов объекта, возможность изменить внутреннюю реализацию без влияния на код клиентов.

2. Наследование (Inheritance)

Читать полностью ->
Какие знаешь итераторы?
1.3 Junior🔥 27💬 1

Какие знаешь итераторы?

Итераторы — это одна из центральных абстракций в C++ STL. Это обобщение указателей, позволяющее единообразно работать с разными контейнерами.

Категории итераторов

Итераторы организованы в иерархию по мощности:

1. Random Access Iterator (самый мощный)

Позволяет произвольный доступ, как обычный указатель: доступ по индексу O(1), арифметика, сложение с числом, сравнение.

Контейнеры: std::vector, std::deque, std::array, std::string

2. Bidirectional Iterator

Можно идти вперёд и назад. Но NO random access.

Контейнеры: std::list, std::set, std::map, std::multiset, std::multimap

3. Forward Iterator

Только вперёд, одна позиция за раз.

Контейнеры: std::forward_list, std::unordered_set, std::unordered_map

4. Input Iterator

Можно только читать, одна позиция за раз. Примеры: std::istream_iterator, std::istreambuf_iterator.

5. Output Iterator

Читать полностью ->
В чем разница между ссылкой и указателем?
1.0 Junior🔥 27💬 1

Разница между ссылкой и указателем в C++

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

Основные различия

Указатель (pointer)

  • Может быть null
  • Может быть переприсвоен на другой объект
  • Требует явного dereference (*ptr)
  • Может выполнять арифметику
int value = 42;
int* ptr = &value;
std::cout << *ptr;  // 42
ptr = nullptr;      // OK

Ссылка (reference)

  • НЕ МОЖЕТ быть null (всегда указывает на объект)
  • НЕ МОЖЕТ быть переприсвоена (один раз создана - на всю жизнь)
  • Автоматический dereference (работает как обычная переменная)
  • Нельзя выполнять арифметику
int value = 42;
int& ref = value;
std::cout << ref;   // 42 (без *)
ref = nullptr;      // ОШИБКА компиляции

Ключевые различия в коде

Переприсвоение

int a = 10, b = 20;

int* ptr = &a;
ptr = &b;           // ✅ Указатель переприсвоен на b
Читать полностью ->
Что такое placement new?
1.8 Middle🔥 26💬 1

Placement New: конструирование объектов в предвыделенной памяти

Placement new — это продвинутая техника C++, которая позволяет создавать (конструировать) объекты в уже выделенной памяти, вместо выделения новой памяти. Это не выделяет новую память, а вызывает конструктор объекта в уже существующей области памяти.

Основная синтаксис

// Обычный new — выделяет память И вызывает конструктор
MyClass* obj = new MyClass(args);

// Placement new — вызывает конструктор в существующей памяти
MyClass* obj = new (ptr) MyClass(args);  // ptr — адрес памяти

Практический пример 1: Использование стека

class Point {
public:
    int x, y;
    Point(int x = 0, int y = 0) : x(x), y(y) {
        std::cout << "Constructor called\n";
    }
    ~Point() {
        std::cout << "Destructor called\n";
    }
};
Читать полностью ->
Что такое Mock?
2.0 Middle🔥 26💬 1

Что такое Mock в тестировании

Mock — это имитация реального объекта, которая используется для изоляции компонента при тестировании. Это ключевой инструмент для написания быстрых, надёжных unit тестов.

Основное определение

Mock — это объект-заместитель, который:

  • Имитирует поведение реального объекта (например, БД, HTTP клиента)
  • Позволяет контролировать его входы и выходы
  • Проверяет, как тестируемый компонент взаимодействует с этим объектом
  • Заменяет медленные/сложные зависимости

Различие между Mock, Stub, Fake и Spy

Это часто путают, но это разные инструменты:

// Интерфейс реальной зависимости
class DatabaseInterface {
public:
  virtual ~DatabaseInterface() = default;
  virtual User getUser(int id) = 0;
  virtual void saveUser(const User& user) = 0;
  virtual void deleteUser(int id) = 0;
};
Читать полностью ->
Что происходит на этапе запуска BIOS?
2.7 Senior🔥 26💬 1

Процесс загрузки BIOS

BIOS (Basic Input/Output System) — это первая программа, запускаемая при включении компьютера. Он подготавливает железо для загрузки операционной системы.

Этап 1: POST (Power-On Self-Test)

При включении питания процессор выполняет следующее:

  1. Инициализация процессора — сброс всех регистров, установка режима работы (real mode)
  2. Базовая проверка оборудования — проверка оперативной памяти, видеокарты, дисков
  3. Контрольные суммы — верификация целостности BIOS кода в ROM

Если обнаружены критические ошибки — выводится звуковой сигнал (beep codes), загрузка прерывается.

Этап 2: Инициализация оборудования

BIOS инициализирует:

Читать полностью ->
Что вернет функция std::find_if в случае неудачного поиска?
1.0 Junior🔥 26💬 1

Возвращаемое значение std::find_if при неудаче

std::find_if возвращает итератор на конец диапазона (end iterator) в случае, если элемент, удовлетворяющий условию, не найден.

Сигнатура функции

template<class InputIt, class UnaryPredicate>
InputIt find_if(InputIt first, InputIt last, UnaryPredicate p);

Функция ищет первый элемент в диапазоне [first, last), для которого предикат p возвращает true.

Поведение при успехе и неудаче

#include <algorithm>
#include <vector>
#include <iostream>
Читать полностью ->
Какие плюсы и минусы MFC?
1.3 Junior🔥 26💬 1

Плюсы и минусы MFC (Microsoft Foundation Classes)

MFC — один из старейших C++ фреймворков для разработки Windows приложений. Несмотря на возраст, используется в legacy и enterprise-проектах.

Плюсы MFC

1. Огромное сообщество и документация MFC существует с 1992 года, поэтому в сети огромное количество примеров, туториалов и решений. Разработчик легко найдёт ответ на любой вопрос.

2. Зрелость и стабильность Фреймворк прошёл проверку временем, используется в тысячах production-приложений. Баги давно найдены, API стабилен и не меняется.

3. Полная интеграция с Windows API MFC — тонкая обёртка над WinAPI, позволяет легко добраться до низкоуровневых функций системы без ненужных абстракций.

4. Производительность Приложения очень быстрые — нативный код без лишних слоёв абстракции. Минимальные накладные расходы.

5. Встроенные компоненты Включает поддержку диалогов, меню, базовых контролов, документов, drag-and-drop и других UI элементов из коробки.

Читать полностью ->
Какие знаешь спецификаторы методов?
1.3 Junior🔥 26💬 1

Спецификаторы методов в C++

Спецификаторы методов — ключевые слова, которые определяют поведение, доступность и особенности работы методов класса. Это критические инструменты для создания безопасного и предсказуемого кода.

1. const спецификатор

const метод — метод, который не изменяет состояние объекта. Гарантирует, что на члены-данные не будут изменены.

class String {
public:
    int length() const {  // const метод
        return str.size();
    }
    
    void setContent(const std::string& s) {  // non-const метод
        str = s;
    }
    
private:
    std::string str;
};

const String immutable = "hello";
immutable.length();        // OK - const метод
immutable.setContent("world");  // ERROR - non-const метод!

Преимущества:

  • Контракт: явное обещание не менять состояние
  • Оптимизация: компилятор может оптимизировать const методы
  • Безопасность: объект const ссылка может вызывать только const методы

2. virtual спецификатор

Читать полностью ->
Как работает виртуальность в C++?
1.7 Middle🔥 26💬 1

Как работает виртуальность в C++

Основная идея

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

Это основа полиморфизма в C++.

Простой пример

class Animal {
public:
    virtual void speak() {
        std::cout << "Some sound\n";
    }
};

class Dog : public Animal {
public:
    void speak() override {
        std::cout << "Woof!\n";
    }
};

class Cat : public Animal {
public:
    void speak() override {
        std::cout << "Meow!\n";
    }
};

int main() {
    Dog dog;
    Cat cat;
    
    Animal* animals[] = {&dog, &cat};
    
    for (auto a : animals) {
        a->speak();  // Вызвать нужный speak() в зависимости от реального типа
    }
    // Output:
    // Woof!
    // Meow!
}

Внутреннее устройство: Virtual Method Table (VMT)

Компилятор использует таблицу виртуальных методов для реализации полиморфизма.

Читать полностью ->
Что такое умные указатели?
1.6 Junior🔥 26💬 1

Умные указатели в C++

Умные указатели (smart pointers) — это шаблонные классы, которые обёртывают сырые указатели и автоматизируют управление памятью через RAII паттерн. Это одна из ключевых инноваций Modern C++, избавляющая от необходимости вручную вызывать delete.

Основные типы

std::unique_ptr

Уникальный указатель с эксклюзивным владением ресурсом:

std::unique_ptr<MyClass> ptr1(new MyClass());
std::unique_ptr<MyClass> ptr2 = std::move(ptr1);
// ptr1 теперь nullptr, ptr2 владеет объектом
// При выходе ptr2 из области видимости объект удаляется

Особенности:

  • Нулевые накладные расходы (zero-overhead abstraction)
  • Не может быть скопирован (только перемещён)
  • Идеален для исключительного владения
  • Размер = размер указателя (обычно 8 байт)

std::shared_ptr

Разделённое владение ресурсом через подсчёт ссылок (reference counting):

Читать полностью ->
Опишите TCP 3-way handshake.
1.0 Junior🔥 25💬 1

Опишите TCP 3-way handshake

TCP 3-way handshake (трёхсторонний процесс установления соединения) — это последовательность из трёх пакетов, которую выполняют два хоста для установления надёжного TCP-соединения. Этот процесс гарантирует, что оба хоста готовы к обмену данными и синхронизирует начальные номера последовательности (sequence numbers).

Этапы 3-way handshake

Этап 1: SYN (Synchronize)

Клиент → Сервер
├─ Flag: SYN
├─ SEQ: x (начальный номер последовательности клиента)
├─ ACK: 0 (нет подтверждения)
└─ Состояние клиента: SYN_SENT

Этап 2: SYN-ACK (Synchronize + Acknowledge)

Сервер → Клиент
├─ Flag: SYN + ACK
├─ SEQ: y (начальный номер последовательности сервера)
├─ ACK: x + 1 (подтверждение SEQ клиента)
└─ Состояние сервера: SYN_RECEIVED

Этап 3: ACK (Acknowledge)

Клиент → Сервер
├─ Flag: ACK
├─ SEQ: x + 1
├─ ACK: y + 1 (подтверждение SEQ сервера)
└─ Состояние клиента: ESTABLISHED
└─ Состояние сервера: ESTABLISHED
Читать полностью ->
Что такое процесс?
1.0 Junior🔥 25💬 2

Что такое процесс?

Процесс — это экземпляр программы, находящийся в состоянии выполнения в операционной системе. Это не просто код программы, а активный субъект, который имеет собственное адресное пространство, системные ресурсы и состояние.

Основные компоненты процесса

Процесс включает:

  • Адресное пространство памяти (код, данные, стек, куча)
  • Идентификатор процесса (PID) — уникальный номер в системе
  • Таблицу открытых файлов (файловые дескрипторы)
  • Переменные окружения и аргументы командной строки
  • Регистры процессора и счётчик команд
  • Приоритет и расписание выполнения
  • Информацию о владельце (UID, GID)

Жизненный цикл процесса

Процесс может находиться в состояниях:

  1. Ready — готов к выполнению, ждёт CPU
  2. Running — выполняется на процессоре
  3. Waiting — ожидает события (I/O, сигнал)
  4. Zombie — завершился, но родитель не прочитал статус
  5. Terminated — полностью удалён из системы
Читать полностью ->
Что такое FTP протокол?
1.2 Junior🔥 25💬 1

Протокол FTP (File Transfer Protocol)

FTP — один из самых старых и всё ещё используемых протоколов для передачи файлов. Хотя во многом устаревший, знание FTP важно для backend-разработчика, работающего с legacy системами.

Что такое FTP?

FTP (File Transfer Protocol) — это протокол прикладного уровня (Layer 7 OSI) для передачи файлов между компьютерами в сети. Он работает на TCP/IP и использует два отдельных соединения: одно для команд, другое для данных.

Основная идея: клиент подключается к FTP серверу, аутентифицируется (или входит как anonymous), затем может загружать, скачивать, удалять, переименовывать файлы.

Архитектура: два соединения

Это ключевое отличие FTP от HTTP:

Control connection (Port 21)

  • Используется для команд: USER, PASS, LIST, RETR, STOR, DELETE, etc.
  • Постоянное, остаётся открытым во время сессии
  • Текстовый протокол (ASCII команды и ответы)
Читать полностью ->
Что происходит при выбрасывании исключения из конструктора?
1.0 Junior🔥 25💬 1

Что происходит при выбрасывании исключения из конструктора?

Краткий ответ

Когда из конструктора выбрасывается исключение:

  1. Объект считается невалидным и не полностью инициализирован
  2. Уже выделенная память освобождается
  3. Деструктор НЕ вызывается (объект не был создан)
  4. Управление передаётся обработчику исключения

Детальный процесс

class Resource {
public:
    Resource(int id) {
        std::cout << "Конструктор начался\n";
        if (id < 0) {
            throw std::invalid_argument("ID не может быть отрицательным");
        }
        this->id = id;
        std::cout << "Конструктор завершился успешно\n";
    }
    
    ~Resource() {
        std::cout << "Деструктор вызван\n";
    }
    
private:
    int id;
};
Читать полностью ->
Какую структуру данных выберешь для хранения большого количества целых чисел с частой операцией добавления?
1.3 Junior🔥 25💬 1

Выбор структуры данных для хранения целых чисел с частым добавлением

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

1. std::vector (Динамический массив)

Лучший выбор в большинстве случаев:

#include <vector>

std::vector<int> numbers;

// Добавление элементов
for (int i = 0; i < 1000000; i++) {
    numbers.push_back(i);  // Амортизированная O(1)
}

// Резервирование памяти заранее
numbers.reserve(1000000);  // Избегаем лишних переаллокаций

// Итерирование очень быстро
for (int num : numbers) {
    // Доступ: O(1)
}

Преимущества:

  • Амортизированная сложность O(1) для push_back
  • Кэш-дружественный (линейное расположение в памяти)
  • Очень быстрый доступ по индексу O(1)
  • Минимальный оверхед памяти
Читать полностью ->
Какой контейнер лежит в основе map?
1.8 Middle🔥 25💬 1

Какой контейнер лежит в основе map?

map в C++ Standard Library строится на основе красно-чёрного дерева (Red-Black Tree). Это самобалансирующееся бинарное дерево поиска, которое обеспечивает эффективность операций благодаря поддержанию баланса.

Почему именно красно-чёрное дерево?

Красно-чёрное дерево выбрано потому, что оно гарантирует:

  • O(log n) для поиска, вставки и удаления элементов
  • Автоматическая балансировка при каждой модификации
  • Предсказуемая производительность — нет деградации к O(n) как в несбалансированных деревьях
  • Итераторы остаются валидными после операций (за исключением удаляемого элемента)
  • Упорядоченный обход в отсортированном порядке ключей

Структура узла красно-чёрного дерева

struct Node {
    Key key;
    Value value;
    Node* left;
    Node* right;
    Node* parent;
    Color color;  // RED или BLACK
};

Правила красно-чёрного дерева

Читать полностью ->
Как устроен std::set?
2.0 Middle🔥 25💬 1

Устройство std::set

std::set — это контейнер стандартной библиотеки C++, который хранит уникальные элементы в отсортированном порядке. Понимание его внутреннего устройства критично для написания эффективного кода.

Внутренняя структура: красно-чёрное дерево

std::set реализован на основе красно-чёрного дерева (red-black tree) — сбалансированного бинарного дерева поиска:

// Упрощённая структура узла
template<typename T>
struct Node {
    T value;
    Node* left;
    Node* right;
    Node* parent;
    Color color;  // RED или BLACK
};

Свойства красно-чёрного дерева

  • Каждый узел окрашен в красный или чёрный цвет
  • Корень всегда чёрный
  • Листья (nullptr) считаются чёрными
  • Красный узел имеет только чёрных детей (нет двух красных подряд)
  • Все пути от корня к листьям имеют одинаковое количество чёрных узлов

Эти свойства гарантируют, что высота дерева всегда O(log n).

Сложность операций

std::set<int> s;
Читать полностью ->
Как устроен Map?
2.0 Middle🔥 25💬 1

Как устроен Map в C++

std::map — это упорядоченный контейнер, который хранит пары ключ-значение в отсортированном порядке по ключам. Это один из фундаментальных контейнеров стандартной библиотеки C++, и понимание его внутреннего устройства критично для написания эффективного кода.

Внутренняя структура: Red-Black Tree

std::map реализует свои данные с помощью красно-чёрного дерева (Red-Black Tree) — это самобалансирующееся двоичное дерево поиска:

#include <map>
#include <iostream>

int main() {
    // Внутренняя структура map:
    //        [5]
    //       /   \
    //      [3]   [7]
    //     / \   / \
    //   [1][4][6][8]
    
    std::map<int, std::string> map;
    map[5] = "five";
    map[3] = "three";
    map[7] = "seven";
    
    // Элементы хранятся в отсортированном порядке
    for (auto& [key, value] : map) {
        std::cout << key << ": " << value << std::endl;  // 3, 5, 7
    }
}

Свойства Red-Black Tree

Читать полностью ->
Как происходит сборка проекта?
1.2 Junior🔥 25💬 1

Ответ: Сборка C++ - многоэтапный процесс от источника к исполняемому файлу

Процесс сборки (build) C++ проекта состоит из нескольких этапов: препроцессинг, компиляция, оптимизация и линковка.

Этап 1: Препроцессинг (Preprocessing)

// main.cpp
#include <iostream>
#define MAX 100
#ifdef DEBUG
    #define PRINT(x) std::cout << x << std::endl
#else
    #define PRINT(x)
#endif

int main() {
    PRINT("Hello");
    return 0;
}

Препроцессор (обычно cpp):

  1. Раскрывает #include - вставляет содержимое файла
  2. Обрабатывает макросы - заменяет #define
  3. Удаляет комментарии
  4. Обрабатывает условную компиляцию (#ifdef, #if)
g++ -E main.cpp > main.i  # Выводит результат препроцессинга

Результат: файл main.i с развёрнутыми include и макросами.

Этап 2: Компиляция (Compilation)

Компилятор (gcc, clang) преобразует исходный код в ассемблер:

g++ -S main.cpp  # Создаёт main.s (ассемблер)
Читать полностью ->
Как послать сигнал процессу?
1.0 Junior🔥 25💬 1

Как послать сигнал процессу

Что такое сигналы

Сигналы — это способ асинхронной коммуникации между процессами в Unix/Linux. Это программное прерывание, которое может заставить процесс выполнить определённое действие.

Основные сигналы:

  • SIGTERM (15): мягкое завершение процесса (по умолчанию)
  • SIGKILL (9): принудительное завершение (нельзя перехватить)
  • SIGSTOP (19): остановить процесс (нельзя перехватить)
  • SIGCONT (18): возобновить остановленный процесс
  • SIGHUP (1): перезагрузить конфигурацию
  • SIGUSR1, SIGUSR2: пользовательские сигналы для приложения
  • SIGPIPE: попытка записи в закрытый pipe

1. Команда kill из shell

Простейший способ — использовать kill:

# Отправить SIGTERM (15) процессу с PID 1234
kill 1234

# Отправить конкретный сигнал
kill -SIGTERM 1234
kill -15 1234

# Принудительное завершение (SIGKILL)
kill -9 1234

# Остановить процесс
kill -SIGSTOP 1234

# Возобновить процесс
kill -SIGCONT 1234
Читать полностью ->
Как передать параметр в функцию?
1.0 Junior🔥 25💬 1

Способы передачи параметров в функцию на C++

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

1. Передача по значению (Pass by Value)

Параметр копируется при вызове функции. Изменения внутри функции не влияют на оригинальный параметр.

void process_value(int x) {
    x = 100;  // Меняем копию, не оригинал
}

int main() {
    int a = 5;
    process_value(a);
    std::cout << a << std::endl;  // 5 (не изменилось)
}

Преимущества:

  • Простота и независимость функции
  • Невозможно случайно испортить оригинальное значение
  • Удобно для малых объектов

Недостатки:

  • Копирование затратно для больших объектов (vector, string)
  • Лишние операции памяти

Когда использовать:

  • Примитивные типы (int, float, bool)
  • Малые структуры (2-3 поля)

2. Передача по ссылке (Pass by Reference)

Читать полностью ->
Как нравится работать больше: в одиночку или в команде?
1.0 Junior🔥 25💬 1

Предпочтение: Командная работа

С 10+ годами опыта я предпочитаю работать в команде. Это основано на глубоком понимании того, как достигаются лучшие результаты в разработке ПО.

Почему командная работа эффективнее

Разнообразие перспектив

Каждый разработчик видит проблему по-своему. Code review выявляет баги, которые я мог пропустить. Архитектурные решения обсуждаются и улучшаются благодаря разным точкам зрения.

Распределение знания

Нет одного узкого места (single point of failure). Если я в отпуске, проекты не замораживаются. Knowledge sharing позволяет разработчикам учиться друг у друга.

Повышение качества кода

Peer review значительно снижает количество ошибок. Code review — это возможность учиться и развиваться.

Роль опытного разработчика в команде

Читать полностью ->
В каких командах работал
1.0 Junior🔥 25💬 1

Опыт работы в командах

За мою карьеру из более чем 10 лет в системном программировании и разработке backend-систем на C/C++ я имел удовольствие работать в разнообразных командах различных масштабов и направлений.

Высоконагруженные системы (HighLoad)

Текущий проект — это разработка высоконагруженного backend'а для платформы обработки больших данных. Наша команда состоит из 8 инженеров, и мы работаем над:

  • Event processing system — обработка 100k+ событий в секунду
  • Real-time analytics — вычисление агрегатов в реальном времени
  • Distributed caching layer — использование Redis и memcached
  • Message queues — интеграция с RabbitMQ и Kafka

В этом проекте я занимался оптимизацией критических путей, снижением latency с 500ms до 50ms через переписание горячих функций и использование SIMD инструкций.

Микросервисная архитектура

Работал в команде из 15 человек на проекте микросервисной архитектуры для финтеха. Мой вклад:

Читать полностью ->
Что такое полиморфизм в ООП?
1.3 Junior🔥 25💬 1

Полиморфизм в ООП

Полиморфизм — это ключевое понятие объектно-ориентированного программирования, которое означает "многоформность". Это способность объектов разных типов отвечать на один и тот же запрос (вызов метода), но выполняя разные действия в соответствии с их типом. Полиморфизм позволяет писать более гибкий и переиспользуемый код.

Типы полиморфизма

В C++ существует два основных вида полиморфизма:

1. Статический полиморфизм (compile-time)

Перегрузка функций — одна из форм статического полиморфизма, когда несколько функций имеют одно имя, но разные параметры:

void print(int x) { std::cout << "Int: " << x << std::endl; }
void print(double x) { std::cout << "Double: " << x << std::endl; }
void print(const std::string& x) { std::cout << "String: " << x << std::endl; }

print(42);           // Вызовет print(int)
print(3.14);         // Вызовет print(double)
print("Hello");      // Вызовет print(string)
Читать полностью ->
Что такое shared_ptr?
1.0 Junior🔥 25💬 1

shared_ptr в C++

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

Что такое shared_ptr?

shared_ptr — это шаблонный класс, который автоматически управляет жизненным циклом объекта, используя подсчёт ссылок (reference counting). Объект удаляется из памяти только когда на него нет ни одной ссылки.

Как это работает?

#include <memory>

// Создание shared_ptr
std::shared_ptr<int> ptr1(new int(42));
std::shared_ptr<int> ptr2 = ptr1;  // Копирование
std::shared_ptr<int> ptr3 = std::make_shared<int>(42);  // Лучший способ

// Счётчик ссылок = 3 (ptr1, ptr2, ptr3)

ptr1.reset();  // Счётчик = 2
// Объект удаляется только когда счётчик = 0

Ключевые особенности

Читать полностью ->
Когда стоит использовать каждый контейнер из STL?
2.2 Middle🔥 25💬 1

Выбор контейнеров STL

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

Последовательные контейнеры

std::vector

Используй: В 90% случаев это твой выбор по умолчанию.

// Отлично для:
// - Случайный доступ O(1)
// - Стабильная память (iterator invalidation predictable)
// - Удалению в конце (амортизированная O(1))

std::vector<int> v = {1, 2, 3};
v.push_back(4);           // O(1) амортизированная
int x = v[500];           // O(1)
v.erase(v.end() - 1);     // O(1)
v.erase(v.begin());       // O(n) - плохо!

Избегай: Удалений в начале/середине часто. Память: Динамический массив, capacity растёт 1.5x или 2x.

std::deque

Используй: Когда нужны операции O(1) в обоих концах.

// Отлично для:
// - push_back/pop_back O(1)
// - push_front/pop_front O(1) (vector не может!)
// - Случайный доступ O(1)
Читать полностью ->
Что такое выполнение рукопожатия в HTTPS?
2.2 Middle🔥 24💬 1

Что такое выполнение рукопожатия в HTTPS?

HTTPS handshake (рукопожатие) — это процесс установления защищённого соединения между клиентом и сервером перед передачей данных. Это многоэтапный протокол (TLS/SSL), который обеспечивает аутентификацию, согласование алгоритмов шифрования и обмена ключами.

Этапы TLS 1.2 handshake

1. Client Hello

  • Клиент отправляет поддерживаемые версии TLS, cipher suites (комбинации алгоритмов шифрования), расширения
  • Включает случайное число (client random)

2. Server Hello

  • Сервер выбирает из предложенных версию TLS и cipher suite
  • Отправляет свои случайное число (server random)
  • Отправляет certificate (цифровой сертификат с публичным ключом)

3. Проверка сертификата

  • Клиент проверяет подпись сертификата, его цепочку и сроки действия
  • Использует публичный ключ из сертификата
Читать полностью ->