Язык C++ продолжает будоражить умы студентов и профессиональных разработчиков. Быстро этот язык не изучишь, но можно хотя бы эффективно.

Как это сделать и стоит ли вообще начинать?

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

00:25 «Язык» C/C++
01:12 Зачем изучать C++?
02:25 #1. Чистый Си
03:50 #2. Высокоуровневые конструкции
04:51 #3. Практика
06:16 #4. Техническое интервью
06:49 #5. Отладка и дополнение Open Source без гемора со сборкой
09:42 #6. Ресурсы для профессионалов
10:13 Итог

Использованные видео:

Использованная музыка (распространяется на условиях лицензии CC BY 4.0):

  • Chris Zabriskie — CGI Snake
  • Chris Zabriskie — Wonder Cycle

О современных курсах:

Полезные ссылки

Как выбирать материалы

Для быстрого знакомства с языком, помимо стандартного поиска коротких туториалов, погуглите «C++ for Java programmers», где вместо Java — любой язык, который вы уже знаете.

Для остальных случаев — убеждайтесь что дата публикации материала ≥ даты публикации последнего стандарта C++.

В остальном — посмотрите общую статью на тему обучения.

Статический анализ

Убедитесь что правильно включили предупреждения. Для g++ и clang++ это не очень очевидно делается.

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

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

Для продвинутых

Попробуйте освоить язык Rust. Он будет бить вас по рукам в тех случаях, которые вам ранее казались хорошим безопасным кодом. Суть не в том, чтобы остаться на Rust, а в том, чтобы улучшить умения в C++.

Полезные настройки для Gentoo GNU/Linux

# /etc/portage/make.conf
FEATURES="parallel-fetch metadata-transfer splitdebug"
EMERGE_DEFAULT_OPTS="-v --autounmask=y --autounmask-write --keep-going --verbose-conflicts --jobs=20 --load-average=12.0"
MAKEOPTS="-j8 -l8"
CFLAGS="-march=native -O2 -pipe -g -fstack-protector-strong -fdiagnostics-color=always"
CXXFLAGS="${CFLAGS}"
  • что означают FEATURES и прочее — описано в man make.conf
  • содержимое EMERGE_DEFAULT_OPTS — это аргументы к emerge
  • значения --jobs, --load-average и MAKEOPTS настроены под конкретный CPU (в моем случае это i7-6700HQ) так, чтобы выжимать все соки из процессора и собирать всё как можно быстрее (в ущерб возможности пользоваться машиной в это время)
  • CFLAGS — аргументы компилятора

Также учтите, что файлы с отладочной информацией (которые лежат в /usr/lib/debug) захотят много места. В моем случае это 30 GiB.

Включите сохранение core dumps в случае падений

С помощью них вы узнаете где именно упала программа, которая была запущена без отладчика. Делается это так:

# /etc/sysctl.conf
kernel.core_pattern=/coredumps/core_%e.%p
kernel.core_uses_pid = 1

Пользоваться так:

$ stardict
[1]    5285 segmentation fault (core dumped)  /usr/bin/stardict
$ ls /coredumps
core_stardict.5285

Допустим что-то упало. Узнаем что именно упало (на это указывает execfn) и из какого оно пакета:

$ file /coredumps/core_stardict.5285
core_stardict.5285: ELF 64-bit LSB core file, x86-64, version 1 (SYSV), SVR4-style, from 'StarDict', real uid: 1000, effective uid: 1000, real gid: 1000, effective gid: 1000, execfn: '/usr/bin/stardict', platform: 'x86_64'
$ equery b /usr/bin/stardict
app-text/stardict-3.0.6-r3 (/usr/bin/stardict)

Распаковываем исходники пакета, заодно вызываем configure:

$ ebuild /usr/portage/app-text/stardict/stardict-3.0.6-r3.ebuild configure

Смотрим отладчиком где именно упало:

$ gdb /usr/bin/stardict /coredumps/core_stardict.5285
...
(gdb) bt
...
(gdb) list
...
(gdb) thread apply all bt            # для многопоточных программ
...

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

Потом пересобрать и установить измененную версию пакета (с помощью аргументов compile, install и qmerge), с предварительным удалением файла .compiled из временных файлов (которые будут появляться где-то в /var/tmp/portage).

Но сначала я бы проверил наличие бага в более новых версиях пакета, в том числе из системы контроля версий (это ebuild-ы с версией 9999). Если официальный ebuild устарел — можно попробовать поискать неофициальные ebuild-ы в дополнительных репозиториях (так называемых overlays) и добавить эти репозитории с помощью layman.

Также, если баг воспроизводится в отключаемой на стадии сборке пакета подсистеме — то можно выключить эту подсистему с помощью USE-флага и пересобрать пакет.

И не пугайтесь что пока ничего не понятно: это исправится чтением Gentoo Handbook, просмотром YouTube и поиском в Google ;)

Удачи с освоением C++!

Авторство шедевра из шапки поста принадлежит Елене Сагалаеве (aka Алёне C++).