Files
eduplan-cpp-eltex/HR_BASE.md
T

34 KiB
Raw Blame History

База перед тех-скринингом (HR, видеосвязь)

Собрано под вакансию Eltex «Разработчик C/C++» (Новосибирск, 1–3 года, ключевые навыки C/C++, Linux, TCP/IP). Формат — вопрос → короткий ответ. Читать подряд, вслух проговаривая ответы: на скрининге важно не «знаю», а «скажу связно за 20 секунд».


1. ООП (спрашивают почти всегда)

Что такое ООП? Парадигма, где программа — набор объектов, обменивающихся сообщениями; объект объединяет данные и поведение.

Три кита? Инкапсуляция, наследование, полиморфизм. (Иногда добавляют абстракцию.)

Инкапсуляция? Сокрытие внутреннего состояния за публичным интерфейсом: поля private, доступ через методы.

Наследование? Переиспользование и расширение: класс-наследник получает члены базового.

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

Класс и объект? Класс — описание (чертёж), объект — экземпляр в памяти.

struct и class в C++? Разница только в доступе по умолчанию: у struct public, у class private.

Что такое виртуальная функция? Функция, вызываемая по фактическому типу объекта. Реализуется через таблицу виртуальных функций (vtable) — отсюда +указатель на объект.

Зачем виртуальный деструктор? Если удалять наследника через Base* без него — UB, деструктор наследника не вызовется, ресурсы утекут.

Можно ли вызвать virtual из конструктора? Можно, но вызовется версия текущего класса, а не наследника: объект ещё не достроен.

Абстрактный класс? Класс с хотя бы одной чисто виртуальной функцией (= 0), экземпляр создать нельзя. В C++ нет отдельного interface — его роль играет такой класс.

Перегрузка и переопределение — в чём разница? Перегрузка: несколько функций с одним именем и разными параметрами в одной области видимости. Переопределение: virtual-функция наследника с той же сигнатурой.

Что такое static-член? Общий для всех объектов класса, живёт вне объекта; у static-метода нет this.

Что такое SOLID? S — единственная ответственность, O — открыт для расширения/закрыт для изменения, L — подстановка Лисков, I — разделение интерфейсов, D — инверсия зависимостей. Достаточно назвать и объяснить одну-две.

Композиция или наследование? Предпочитают композицию: наследование жёстко связывает классы, композиция гибче.


2. C/C++ (ядро вакансии)

Указатель и ссылка — разница? Указатель — адрес, может быть null, его можно менять и арифметикой ходить. Ссылка — псевдоним существующего объекта, не бывает null, перепривязать нельзя.

new/delete против malloc/free? new вызывает конструктор и возвращает типизированный указатель, malloc даёт сырой блок; new бросает исключение, malloc возвращает NULL; delete вызывает деструктор.

Стек и куча? Стек — автоматическая память (локальные переменные, быстрая, ограничена). Куча — динамическая (new/malloc, больше, но освобождать вручную).

Что такое утечка памяти? Выделили и не освободили. Ищется ASAN (LeakSanitizer), valgrind.

RAII? Ресурс захватывается в конструкторе, освобождается в деструкторе — утечек нет даже при исключениях. Так работают std::vector, std::ifstream, умные указатели.

unique_ptr и shared_ptr? unique_ptr — единственный владелец, без счётчика, дешевле. shared_ptr — общий, считает ссылки, есть накладные расходы и проблема циклических ссылок (weak_ptr).

Правило трёх/пяти? Если класс владеет ресурсом и задан деструктор — надо определить копирование и перемещение (в C++11+: конструктор/присваивание копированием и перемещением).

Что делает std::move? Ничего сам по себе — это static_cast к rvalue-ссылке. Перемещение выполняет конструктор/присваивание перемещением.

Что такое UB? Undefined behavior — стандарт не накладывает требований. Примеры: выход за границы, знаковое переполнение, сдвиг в знаковый бит, разыменование null, гонка данных.

Что проверяют ASAN и UBSAN? ASAN — выходы за границы, use-after-free, двойное освобождение, утечки. UBSAN — неопределённое поведение (переполнения, сдвиги, выравнивание).

sizeof(struct { char a; int b; char c; }) на x86-64? 12: a в 0, padding 1–3, b в 4–7, c в 8, padding 9–11 до выравнивания структуры по 4.

Порядок вычисления аргументов f(a(), b()) задан? Нет, не определён — нельзя полагаться.

Что делает const после сигнатуры метода? Делает this указателем на константу: метод не меняет поля объекта, и его можно вызывать у const-объекта.

Что такое перегрузка операторов и зачем? Своя семантика для +, ==, [] и т.п., чтобы тип вёл себя как встроенный. Нельзя перегружать ., ::, ?:, sizeof.

Компиляция по шагам? Препроцессор (#include, #define) → компиляция в объектные файлы → линковка в исполняемый. Ошибка «undefined reference» — от линковщика.

Зачем header guards? Чтобы заголовок не подключался дважды — иначе повторное определение типа.

Что такое forward declaration? Объявление класса/функции без определения, чтобы не тянуть #include; достаточно для указателей и ссылок.

Что такое шаблон (template)? Обобщённый код, тип подставляется при компиляции. Цена — ошибки и раздувание кода.

Что такое лямбда? Анонимная функция с захватом контекста ([&], [=]). Синтаксический сахар над функтором.

Что такое пространство имён? Способ избежать конфликта имён; std:: — пример.

volatile — что это? Говорит компилятору не кэшировать значение в регистре (регистры железа, переменные, меняемые извне). Это не про многопоточность — для неё std::atomic.


3. STL (обязательно, спрашивают про сложности)

Какие контейнеры знаешь? Последовательные: vector, list, deque, array. Ассоциативные: map, set (деревья, O(log n)). Хеш-таблицы: unordered_map, unordered_set (O(1) в среднем). Адаптеры: stack, queue, priority_queue.

vector — сложности? Доступ по индексу O(1), push_back амортизированное O(1), вставка/удаление в середине O(n), поиск O(n).

Почему push_back амортизированное O(1)? Ёмкость удваивается, реаллокация O(n) случается редко — в среднем одна операция O(1).

list — сложности? Доступ по номеру O(n), вставка/удаление при известном узле O(1), поиск O(n). Память дороже из-за указателей.

map против unordered_map? map — красно-чёрное дерево: O(log n), ключи упорядочены. unordered_map — хеш-таблица: O(1) в среднем, порядок не определён, нужен std::hash.

Что быстрее и когда? Поиск — обычно unordered_map. Если нужен порядок обхода или диапазонные запросы — map.

Итераторы и их инвалидация? Итератор — обобщённый указатель на элемент. У vector реаллокация инвалидирует все итераторы, у list — только итератор удалённого элемента.

Как удалить элементы из vector по условию? Идиома erase-remove: v.erase(std::remove_if(v.begin(), v.end(), pred), v.end());.

reserve и resize? reserve меняет ёмкость (память), не размер. resize меняет размер (создаёт/удаляет элементы).

emplace_back против push_back? emplace_back конструирует объект на месте — без копирования/перемещения.

Как работает priority_queue? Бинарная куча поверх vector: вставка O(log n), извлечение максимума O(log n), доступ к максимуму O(1). По умолчанию max-куча.

Какие алгоритмы STL знаешь? sort (O(n log n), неустойчив), stable_sort, find, count, lower_bound/upper_bound (O(log n) на отсортированном), accumulate, remove_if, unique, next_permutation.

Что такое функтор и предикат? Объект с operator(). Предикат — функция/функтор, возвращающий bool, используется в алгоритмах.

string — это контейнер? Да, std::basic_string<char>: size(), substr, find, append; данные лежат непрерывно, .c_str() даёт C-строку.


4. Linux и ОС

Процесс и поток? Процесс — программа в исполнении со своим адресным пространством и PID. Поток — единица выполнения внутри процесса: общая память, свой стек и регистры.

Что делает fork()? Создаёт копию процесса. Возвращает дважды: в родителе — PID ребёнка, в ребёнке — 0, при ошибке −1.

Что с памятью при fork()? Copy-on-write: страницы общие, копируются при первой записи.

exec? Заменяет образ текущего процесса (код, данные, стек). При успехе не возвращается. fork + exec — запуск внешней программы.

Зачем waitpid? Забрать код возврата и не оставлять зомби.

Зомби и сирота? Зомби — завершившийся процесс, чья запись ждёт wait. Сирота — процесс, чей родитель умер; его усыновляет init (PID 1).

Коды возврата 137 и 139? 137 = 128+9 (SIGKILL), 139 = 128+11 (SIGSEGV). Так кодирует оболочка.

Сигналы, основные? SIGINT (2, Ctrl+C), SIGKILL (9, не перехватить), SIGTERM (15, корректное завершение), SIGSEGV (11), SIGPIPE (13, запись в закрытый сокет), SIGCHLD (17).

SIGTERM против SIGKILL? SIGTERM можно перехватить и завершиться аккуратно, SIGKILL нельзя ни перехватить, ни проигнорировать.

Файловый дескриптор? Число, по которому программа обращается к открытому файлу, сокету, pipe. 0/1/2 — stdin/stdout/stderr.

Что такое epoll? Механизм мультиплексирования: ядро сообщает о готовых дескрипторах, сложность O(1) на событие. select/poll перебирают все дескрипторы — O(n).

mmap? Отображает файл в память: страницы подгружаются по обращению, вместо read/write работаешь с указателем.

Виртуальная память и страница? Каждому процессу — своё адресное пространство; память делится на страницы (обычно 4 КБ), отображаемые на физическую.

Что такое swap? Выгрузка страниц на диск при нехватке памяти. Медленно, но спасает от OOM.

Что такое inode? Структура метаданных файла (права, размер, владелец, указатели на блоки). Имя файла — отдельно, в каталоге.

Права доступа 755? Владелец rwx, группа r-x, остальные r-x. chmod, chown — смена прав и владельца.

Что такое pipe и перенаправление? | соединяет вывод одной программы со входом другой; >, >>, 2>&1 перенаправляют потоки.

Как посмотреть процессы и нагрузку? ps aux, top/htop, pidstat; free -h — память, df -h — диски, iostat — ввод-вывод.

Что такое демон? Фоновый процесс без управляющего терминала; запускается systemd (unit-файлы, systemctl start/status).

Что такое ядро и системный вызов? Ядро управляет ресурсами; программа обращается к нему через системные вызовы (open, read, write, fork). strace показывает эти вызовы.

Мьютекс, семафор, атомик? Мьютекс — блокировка на одного владельца. Семафор — счётчик на N владельцев. Атомик — операция без блокировки, аппаратно.

Что такое гонка данных и дедлок? Гонка — несинхронизированный доступ к общей памяти (ловит ThreadSanitizer). Дедлок — потоки ждут ресурсы друг друга; лечится единым порядком захвата.

Условие переменная (condition_variable)? Способ ждать событие: ждать в цикле с предикатом (while (!ready) cv.wait(lock);) — защита от ложных пробуждений.


5. Сети: OSI, TCP/IP, TCP, UDP (ядро вакансии)

Семь уровней OSI? Физический, канальный, сетевой, транспортный, сеансовый, представления, прикладной. Практически работают с пятью.

Что на каждом уровне? L1 — биты и среды (витая пара, оптика). L2 — кадры, MAC, коммутатор. L3 — пакеты, IP, маршрутизатор. L4 — TCP/UDP, порты. L5–L7 — сессии, кодирование, прикладные протоколы (HTTP, DNS).

TCP/IP модель? Канальный, интернет, транспортный, прикладной. Соответствует OSI снизу.

Инкапсуляция? Каждый уровень добавляет свой заголовок: Ethernet (14 байт) → IP (20) → TCP (20) → данные. При передаче пакет кладут внутрь кадра.

Сколько байт в Ethernet-заголовке? 14 (MAC получателя 6, MAC отправителя 6, тип 2). VLAN 802.1Q добавляет 4.

MAC-адрес? 48 бит, физический адрес интерфейса, действует в пределах сегмента.

ARP? Находит MAC по IP в локальном сегменте: широковещательный запрос → ответ.

MTU? Максимальный размер полезной нагрузки кадра, для Ethernet 1500 байт. Больше — фрагментация или ошибка.

IPv4-заголовок, что важно? Минимум 20 байт: версия/IHL, длина, TTL, протокол, контрольная сумма заголовка, адреса источника и назначения. TTL уменьшается на 1 на каждом маршрутизаторе.

Маски и подсети? Маска делит адрес на сеть и узел. /24 — 254 узла, /26 — 62, /30 — 2 (точка-точка). Широковещательный адрес — все единицы в хостовой части.

Маршрутизация? Узел сравнивает адрес со своей маской: своя подсеть — ARP и напрямую, чужая — на шлюз. Шлюз по умолчанию — выход в другие сети.

ICMP? Служебные сообщения: ping (echo request/reply), traceroute (истечение TTL), «destination unreachable».

Порядок установки TCP-соединения? SYN → SYN-ACK → ACK (трёхстороннее рукопожатие).

Как закрывается TCP? FIN → ACK → FIN → ACK; сторона, закрывшая первой, ждёт TIME_WAIT (2×MSL), чтобы добить потерянные сегменты.

Флаги TCP? SYN, ACK, FIN, RST, PSH, URG.

Что даёт TCP? Надёжность: нумерация, подтверждения, ретрансмиссии по таймауту, окно (управление потоком), контроль перегрузки, сохранение порядка.

Что такое окно? Сколько байт можно отправить без подтверждения. Управляет скоростью и защищает от переполнения получателя.

UDP? Без соединения и гарантий: заголовок 8 байт, порядок и доставка не гарантируются. Быстро и дёшево: DNS, DHCP, VoIP, игры, стриминг.

TCP или UDP — когда что? TCP — когда важна целостность (файлы, HTTP, SSH). UDP — когда важна задержка или данные самодостаточны (DNS, видео, телеметрия).

Что такое порт? Номер приложения на узле (16 бит). Известные: 22 SSH, 53 DNS, 80 HTTP, 443 HTTPS.

DNS? Превращает имя в IP. Обычно UDP/53, при больших ответах — TCP/53.

DHCP? Автоматическая выдача IP, маски, шлюза, DNS.

NAT? Подмена адресов при выходе в интернет: много внутренних устройств через один внешний IP.

Сокеты: как устроен сервер? socket → bind → listen → accept → read/write → close. Клиент: socket → connect. Для множества соединений — epoll и неблокирующие сокеты.

Что такое неблокирующий сокет и EAGAIN? Вызов не ждёт данных: если их нет, возвращает −1 и errno = EAGAIN — надо вернуться позже.

Чем смотрят трафик? tcpdump, Wireshark. Базово: tcpdump -i eth0 -nn port 80.


6. Многопоточность (в вакансии: многопоточные приложения)

Как создать поток в C++? std::thread t(f, args); t.join(); (или detach, но тогда следи за временем жизни).

Как защитить общие данные? std::mutex + std::lock_guard/std::unique_lock; для счётчиков — std::atomic.

Что такое ложное пробуждение? wait может вернуться без сигнала — поэтому ждут в цикле с предикатом.

Как избежать дедлока? Единый порядок захвата мьютексов, std::lock/std::scoped_lock для нескольких сразу, не держать блокировку при вызове чужого кода.

Producer/consumer — как? Очередь + мьютекс + condition_variable: производитель кладёт и уведомляет, потребитель ждёт и забирает.

Пул потоков зачем? Создание потока дорого; пул переиспользует N потоков и очередь задач.

Потокобезопасный size()? Нужен либо атомарный счётчик, либо мьютекс: без этого чтение и запись — гонка данных.


7. Git

Основной цикл работы? git clone → git checkout -b feature → правки → git add → git commit → git push → pull request.

Что такое коммит, ветка, HEAD? Коммит — снимок состояния с родителями. Ветка — подвижный указатель на коммит. HEAD — где ты сейчас.

merge и rebase? merge создаёт коммит слияния, история ветвится. rebase переносит коммиты поверх другой ветки — история линейная, но переписываются хеши.

Конфликт — что делать? Git помечает файлы, правишь вручную, git add, git merge --continue (или --abort).

reset, revert, checkout? reset двигает ветку (может потерять коммиты), revert создаёт обратный коммит — безопасно для общей ветки, checkout/switch переключает ветки и файлы.

stash? Отложить незакоммиченные изменения: git stash, потом git stash pop.

fetch и pull? fetch скачивает без слияния, pull = fetch + merge (или rebase).

Как посмотреть историю и что менялось? git log --oneline --graph, git diff, git show <commit>, git blame.

Что не коммитить? Секреты, артефакты сборки, большие бинарники — через .gitignore.


8. Docker

Образ и контейнер? Образ — неизменяемый шаблон (слои файловой системы). Контейнер — запущенный экземпляр образа плюс своё изменяемое состояние.

Чем отличается от виртуальной машины? Контейнер использует ядро хоста и изолирует процессы (namespaces, cgroups) — легче и стартует за секунды; VM несёт своё ядро.

Dockerfile — ключевые инструкции? FROM, RUN, COPY, WORKDIR, ENV, CMD/ENTRYPOINT, EXPOSE.

Зачем слои и порядок инструкций? Каждая инструкция — слой, слои кэшируются; часто меняющееся (код) ставят после редко меняющегося (зависимости), чтобы кэш работал.

Volume и bind mount? Volume — управляемое Docker хранилище (данные переживают контейнер). Bind mount — каталог хоста внутри контейнера.

Сети в Docker? По умолчанию bridge с внутренними IP; порты публикуются через -p 8080:80. Есть host и overlay для swarm.

docker-compose? Описание нескольких сервисов в одном YAML: docker compose up -d.

Где это в Eltex? Воспроизводимая сборка и тесты: один образ у всех, «у меня работает» перестаёт быть аргументом.


9. GDB и отладка

Как запустить? g++ -g -O0 prog.cpp -o prog (обязательно -g), затем gdb ./prog, run.

Основные команды? break main / break file:line, run, next (по шагам, через вызовы), step (внутрь), continue, print x, bt (стек вызовов), frame N, watch var, info threads.

Как отладить падение? Запустить, получить bt, посмотреть кадр с падением, print указателей; либо core dump (ulimit -c unlimited, затем gdb prog core).

Что такое core dump? Снимок памяти процесса в момент падения; позволяет разобраться постфактум.

Санитайзеры? ASAN (память), UBSAN (UB), TSan (гонки), MSan (неинициализированная память) — включаются флагом -fsanitize=....

valgrind? Инструмент поиска утечек и ошибок памяти без пересборки; медленнее санитайзеров.


10. Bash и инструменты

Что такое скрипт и его шапка? #!/usr/bin/env bash плюс set -euo pipefail — падать на ошибках, на необъявленных переменных и в конвейерах.

Переменные и аргументы? name=value, $name, $1..$9, $#, $@, $? (код возврата), $$ (PID).

grep, awk, sed — для чего? grep — поиск по шаблону, awk — обработка по колонкам и подсчёты, sed — замена/правка потока. Для больших файлов — только они, а не bash-цикл по строкам.

Пайплайны и перенаправления? cmd1 | cmd2, >, >>, 2>, 2>&1, tee.

Как найти файлы и выполнить команду? find /path -name '*.log' -mtime -1, find ... -exec ... {} +, xargs.

Полезное на каждый день? ps/top, ss -tulpn (порты), df -h, du -sh, tail -f, journalctl -u сервис, systemctl status.


11. Embedded и SoC (в вакансии «плюс», знать обзорно)

Что такое bringup? Запуск новой платы: uboot → ядро → корневая ФС → периферия. Задача — довести устройство до стабильной работы.

uboot? Загрузчик: инициализирует железо, грузит ядро и передаёт ему параметры (device tree).

Модуль ядра? Код, загружаемый в ядро (insmod/rmmod), с init/exit; печатает через printk, видно в dmesg.

Символьный драйвер? Даёт доступ к устройству как к файлу через file_operations (open, read, write, ioctl).

Device tree? Описание железа (адреса, прерывания, шины) для ядра — отдельно от кода.

Cross-compile? Сборка под другую архитектуру (например ARM на x86) тулчейном arm-linux-gnueabihf-gcc.

Что сказать честно? Опыта продуктовой разработки драйверов нет, теорию знаю: модуль, драйвер, device tree, cross-compile; готов добирать на месте.


12. Вопросы, которые задаст HR (и хорошие ответы)

Расскажи о себе. 40 секунд: кто, сколько лет в разработке, на чём пишешь (C/C++, Linux), чем занимался последним, почему интересна встраиваемая разработка и сети.

Почему Eltex? Продукт настоящий и низкоуровневый: коммутаторы, маршрутизаторы, GPON. Хочу расти в C++/Linux/сетях на реальном железе, а не на абстрактных сервисах.

Что знаешь о компании? Более 2000 человек, Новосибирск, телекоммуникационное оборудование (Ethernet-коммутаторы, сервисные маршрутизаторы, Wi-Fi, GPON, IoT), свои SoC-устройства.

Почему уходишь с текущего места? Без негатива: хочу ближе к системной разработке и сетям, где больше глубины.

Готов к офису/гибриду в Новосибирске? Отвечай прямо, как есть; если релокация — скажи, что готов обсуждать сроки.

Ожидания по зарплате? Назови вилку с обоснованием по рынку и добавь «готов обсуждать по итогам интервью».

Сильные и слабые стороны? Сильная — довожу до работающего результата, разбираюсь в отладке. Слабая — называй реальную и что делаешь: например, «раньше писал по памяти, теперь веду заметки и проверяю сложности по коду».

Готов к задачам на алгоритмы? Да, тренируюсь: базовые структуры, сложности, типовые задачи на строки/массивы/графы.

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

Что почитать про нас перед интервью? Сайт Eltex, раздел про продукты и вакансию; интервью и доклады сотрудников на конференциях.


13. Шпаргалка чисел (выучить наизусть)

  • Ethernet-заголовок 14 байт, VLAN-тег +4, MTU 1500.
  • IPv4-заголовок 20 байт, TCP-заголовок 20 байт, UDP-заголовок 8 байт.
  • MAC 48 бит, IPv4 32 бита, порт 16 бит.
  • Подсети: /24 → 254 узла, /26 → 62, /30 → 2.
  • log₂(1000) ≈ 10, log₂(10⁶) ≈ 20.
  • 137 = SIGKILL (128+9), 139 = SIGSEGV (128+11), 143 = SIGTERM (128+15).
  • Порты: 22 SSH, 53 DNS, 80 HTTP, 443 HTTPS.