Обложка канала

Sea++

Канал об интересных материалах из мира C/C++, Python, Go, Linux и не только. Новости, заметки, полезные советы и многое другое.

  • Sea++

    ​​#реклама

    Интересуетесь этичным хакингом? Приглашаем на демо-занятие «Проверка публичных PoC для использования при пентесте», которое является частью практического онлайн-курса «Пентест. Практика тестирования на проникновение».
    20 августа в 20:00 вебинар проведет преподаватель-практик Александр Колесников, вирусный аналитик из межднародной компании.

    На занятии вы рассмотрите несколько proof of concepts для уязвимостей в программном обеспечении и настроите окружение для их теста. А также обсудите возможности их модификации для использования в metasploit framework.

    Для регистрации на демо-занятие пройдите вступительный тест https://otus.pw/TE5z/
  • Sea++

    "Drop ban on mutable references"

    English version: https://telegra.ph/Drop-ban-on-mutable-references-05-27

    Случилось эпохальное событие: Google отменил бан для неконстантных ссылок в праметрах функций.

    https://google.github.io/styleguide/cppguide.html#Inputs_and_Outputs
     Parameters are either input to the function, output from the function, or both. Input parameters should usually be values or const references, while required (non-nullable) output and input/output parameters should usually be references.

    https://github.com/google/styleguide/pull/553
  • Sea++

    Entity Component System (ECS)

    English version: https://telegra.ph/Entity-Component-System-ECS-02-10

    Все мы неоднократно слышали о чудесах объектно-ориентированного программирования (ООП), позволяющих контролировать сложность программ, которые мы разрабатываем. Объект реального мира сопоставляется объекту какого-либо класса в коде. Вспомним, к примеру, хрестоматийный пример с Animal, Dog, Cat и т.д.

    Но оказывается, игровая индустрия уже давно ушла от ООП в сторону Data Oriented Design (DOD), дизайна программ основанного на данных. Вот главные причины:
    • ООП в случае игр больше вредит, чем помогает. Появляется всемогущий SuperObject, который определяет все методы всех наследников (а это очень много даже в случае игр среднего размера)
    • Обдумывание архитектуры проекта в рамках объектов звучит привлекательно, но чаще всего действия в игре затрагивают две и более сущности, что делает применение методов затруднительным

    Эти и многие другие проблемы ООП в играх рассматривает Кэтрин Вэст (Catherine West) в своем выступлении Using Rust For Game Development на RustConf 2018: https://www.youtube.com/watch?v=aKLntZcp27M

    Кэтрин, как апологет языка Rust, показывает, как использование устаревшего антипаттерна SuperObject в этом языке ведет к бесконечной борьбе с borrow-checker'ом. "Сдавшись", Кэтрин постепенно начинает логично модифицировать архитектуру игры так, что в итоге приходит к Entity Component System (ECS), пожалуй, самой знаменитой реализации концепции Data Oriented/Driven Design, в которую Rust вписывается чуть более, чем полностью. В результате получается гибкая и более производительная система сущностей и компонентов, которые могут быть без труда сериализованы на диск или в сеть.

    Кстати, есть более длинная, но и более интересная версия доклада в виде поста с кодом в блоге Кэтрин: https://kyren.github.io/2018/09/14/rustconf-talk.html
  • Реклама

  • Sea++

    ​​Видеокурс по разработке на С++ от OTUS – это быстрый старт в профессии для начинающих программистов. Подробнее
    👉🏻 https://otus.pw/RRsR/

    Удобный формат
    Доступная цена
    Тестирования после каждого занятия

    #реклама
  • Sea++

    Default initialization — ответ

    English version: https://telegra.ph/Default-initialization--answer-01-30

    Как вы уже наверное поняли, ответ другой.

    Поскольку конструктор для Foo объявлен по умолчанию, он не является user-provided. Это означает, что Foo является агрегатным типом, а f.v инициализируется нулями. Однако Bar имеет пользовательский конструктор, хотя и созданный компилятором как конструктор по умолчанию. Поскольку этот конструктор не инициализирует явно Bar::v, b.v небезопасен для чтения, неопределенное поведение.
  • Sea++

    Default initialization

     struct Foo {
    Foo() = default;

    int v;
    };

    struct Bar {
    Bar();

    int v;
    };

    Bar::Bar() = default;

    int main() {
    Foo f = {};
    Bar b = {};
    }

    Как вы думаете, чему равно значение f.v и b.v?
    Ответ с объяснением будет завтра.

    What are the values of f.v and b.v?
    An answer with an explanation will be tomorrow.
  • Sea++

    VVVVVV??? VVVVVV!!! :)

    Если вы читаете этот текст – значит, вы либо подумали, что с заголовком статьи что-то не то, либо увидели в нём название знакомой компьютерной игры. VVVVVV – это инди-игра в жанре «платформер», завоевавшая сердца многих игроков своей приятной внешней простотой и не менее приятной внутренней сложностью.

    Несколько дней назад VVVVVV исполнилось 10 лет, и автор игры – Terry Cavanagh – отметил этот праздник публикацией её исходного кода. Мимо такой новости не могла пройти команда PVS-Studio, разрабатывающая инструмент по поиску ошибок и потенциальных уязвимостей в исходном коде программ. Что же «вкусненького» нашлось в этом проекте? Ответ читайте в данной статье.

    https://bit.ly/2RJfQA9

    #реклама

    English version: https://telegra.ph/VVVVVV-VVVVVV-01-23
  • Sea++

    🎄

     #include <stdio.h>

    int main() {
    char z[45];
    z[0] = 'b' - 26;
    z[30] = ':' + 40;
    z[6] = 60 + 18;
    z[2] = 83 + 29;
    z[43] = 101;
    z[9] = ' ' + 0;
    z[37] = 106;
    z[34] = 106;
    z[40] = 'q' - 3;
    z[8] = 81 + 38;
    z[13] = 48 + 0;
    z[10] = 50;
    z[26] = 'I' + 28;
    z[39] = 'G' + 39;
    z[33] = 103;
    z[23] = 122 - 17;
    z[15] = 89;
    z[20] = 33 + 0;
    z[4] = 'z' - 1;
    z[29] = 121 - 17;
    z[41] = 122;
    z[36] = 105 - 0;
    z[25] = 120;
    z[21] = 82 - 49;
    z[31] = 'u' - 2;
    z[11] = 48 + 0;
    z[28] = 'g' - 4;
    z[17] = ']' + 4;
    z[44] = 14 - 14;
    z[42] = 120;
    z[1] = 97;
    z[5] = ' ' + 0;
    z[35] = 'J' + 44;
    z[22] = '^' - 94;
    z[7] = 107 - 6;
    z[38] = 79 + 39;
    z[24] = 'q' - 13;
    z[3] = 'u' - 5;
    z[32] = 101;
    z[18] = 114;
    z[12] = 72 - 22;
    z[14] = ' ' + 0;
    z[27] = 't' - 5;
    z[19] = 33;
    z[16] = 113 - 12;
    puts(z);
    }

    http://cpp.sh/4mhdz
  • Sea++

    ​​☝🏻19 декабря в 20:00 (мск) – День Открытых Дверей онлайн-курса «Разработчик C++».

    ❗️Запишитесь, чтобы не пропустить: https://otus.pw/BEYH/

    🗣Встречу проведет преподаватель курса, Сергей Кольцов – TeamLead C++ в компании VisionLabs, опытный разработчик и инженер с более чем 10 летним стажем.

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

    Остались вопросы? Задайте их преподавателю лично в прямом эфире!

    🎁А также приглашаем пройти вступительный тест и поступить в группу со скидкой -30%: https://otus.pw/Mua8/
    #реклама
  • Sea++

    Google Test v1.10.0

    English version: https://telegra.ph/Google-Test-v1100-12-16

    Относительно недавно вышла версия v1.10.0 Google C++ Test/Mock фреймворка для юнит-тестирования.

    Ключевая особенность: теперь не нужно указывать число аргументов у переопределямого метода mock-класса. То есть вместо
     MOCK_METHOD1(Bar, double(std::string s));

    можно писать просто
     MOCK_METHOD(double, Bar, (std::string s), (override));

    Подробнее: https://github.com/google/googletest/blob/72adf7a4155b6642da1e6761678fe546590c0269/googlemock/docs/cook_book.md#creating-mock-classes
  • Sea++

    likely/unlikely

    English version: https://telegra.ph/likelyunlikely-11-27

    Многие задают вопрос про последнюю статью: что это за атрибут [[unlikely]]? Этот атрибут взят из черновика стандарта C++20: https://en.cppreference.com/w/cpp/language/attributes/likely

    Он подсказывает компилятору, какая ветка условия или case в switch выражении выполняется чаще.
    На x86/x64 компилятор поместит likely-ветку в ассемблере сразу же после проверки условия, максимально утилизируя кэш инструкций процессора. Никакого статического предсказания перехода тут нет. Однако не удивлюсь, что в какой-нибудь архитектуре PowerPC найдется отдельная инструкция для подсказки предсказателю переходов.

    В компиляторах пока еще нет поддержки likely/unlikely атрибутов, но зато есть расширения:
     #define likely(x) __builtin_expect(!!(x), 1)
    #define unlikely(x) __builtin_expect(!!(x), 0)

    Пример (только Clang и GCC), где ожидаем, что IsValid() чаще будет возвращать true:
     bool IsValid();
    int Bar();
    int Baz();

    int Foo() {
    if (likely(IsValid()))
    return Bar();
    else
    return Baz();
    }

    Ассемблер:
     Foo():  # @Foo()
    push rax
    call IsValid()
    test al, al
    je .LBB0_2
    pop rax
    jmp Bar() # TAILCALL
    .LBB0_2:
    pop rax
    jmp Baz() # TAILCALL

    Пример, где ожидаем, что IsValid() чаще будет возвращать false:
     bool IsValid();
    int Bar();
    int Baz();

    int Foo() {
    if (unlikely(IsValid()))
    return Bar();
    else
    return Baz();
    }

    Ассемблер:
     Foo():  # @Foo()
    push rax
    call IsValid()
    test al, al
    jne .LBB0_1
    pop rax
    jmp Baz() # TAILCALL
    .LBB0_1:
    pop rax
    jmp Bar() # TAILCALL

    Можно заметить, что компилятор ставит сразу после проверки (команда test) соответствующую нашей подсказке ветку кода. Это потенциально может дать неплохое ускорение, если все правильно разметили (а ведь можно дать и неверную подсказку).
    Нужно еще иметь ввиду, что сейчас процессоры очень хорошо предсказывают ветвления, так что разницу можно особо и не заметить.
  • Sea++

    Status macros

    English version: https://telegra.ph/Status-macros-11-14

    В продолжение к предыдущему посту об удобном способе обработки ошибок в C++.

    В гугловых проектах используются специальные классы Status и StatusOr<T> (см. https://t.me/sea_plus_plus/23), которые возвращаются из методов, в которых может произойти ошибка, например
    Status WriteToFile(std::string_view content);
    или
    StatusOr<std::string> ReadFromFile();

    Обычным способом проверки является if:
    Status Write(std::string_view content) {
    Status status = WriteToFile(content);
    if (!status.ok())
    return status;

    return Status::OK();
    }

    StatusOr<std::string> Read() {
    StatusOr<std::string> content = ReadFromFile();
    if (!content.ok())
    return content.status();

    return content.ValueOrDie();
    }

    Но это громоздко. В основном, используются специальные макросы (https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/stubs/status_macros.h):
    Status Write(std::string_view content) {
    RETURN_IF_ERROR(WriteToFile(content));
    return Status::OK();
    }

    StatusOr<std::string> Read() {
    std::string content;
    ASSIGN_OR_RETURN(content, ReadFromFile());
    return content;
    }

    Макросы, в общем случае, не рекомендуется использовать в C++. Но тут, на мой взгляд, они вполне оправданы. К тому же в if внутри макроса можно поставить атрибут [[unlikely]] и получить прирост в производительности, а так пришлось бы в каждый if писать ее явно. В общем, в этом случае только польза.
  • Sea++

    Try, Go, Try!

    English version: https://telegra.ph/Try-Go-Try-10-28

    Некоторое время назад в среде Go появилось предложение о введении встроенной функции проверки ошибок try (https://go.googlesource.com/proposal/+/master/design/32437-try-builtin.md, https://habr.com/ru/post/472758/) за авторством Роберта Гризмера.

    Это нужно для устранения повторяющихся проверок
     if err != nil {
    return nil, err
    }

    о которых не говорил только ленивый.

    К слову, это уже не первое предложение ввести новые языковые конструкции для обработки ошибок. Уже были check и handle, о которых я уже писал (https://t.me/sea_plus_plus/77)

    В новом предложении
     f := try(os.Open(filename))

    будет развернуто компилятором в
     f, err := os.Open(filename)
    if err != nil {
    return nil, err
    }
    что весьма удобно.

    handle не прижился из-за того, что был очень сильно похож на уже имеющийся механизм defer.

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

    UPD: предложение все же было закрыто.

    Между прочим, C++ тоже не хватает, на мой взгляд, возможности выйти сразу из нескольких стек фреймов. Это проблему можно решить, к примеру, используя нестандартное расширение GCC и макросы: https://github.com/google/lmctfy/blob/master/util/errors.h#L229

    И писать
     std::string s = RETURN_IF_ERROR(FunctionReturnsStatusOrString());
    получая здесь практически все то же самое, что дает try в Go.
  • Sea++

    Google Abseil Btree

    В C++ библиотеку Google Abseil https://github.com/abseil/abseil-cpp/tree/master/absl/container, о которой я уже писал (https://t.me/sea_plus_plus/69), добавили четыре новых STL-like Btree контейнера: absl::btree_map, absl::btree_multimap, absl::btree_set и absl::btree_multiset. Данные хранятся в памяти, но под капотом алгоритм, который пришел из баз данных. Btree хранит несколько элементов в одном блоке памяти, что уменьшает количество аллокаций, а также за счет более эффективного использования кэша работает быстрее в большинстве случаев.

    Это практически drop-in замена std::map и std::set. Однако при вставке и удалении происходит инвалидация итераторов. Поэтому надо быть осторожным.

    English version: https://telegra.ph/Google-Abseil-Btree-10-20
  • Sea++

    https://t.me/sea_plus_plus_chat — официальный чат канала Sea++.
    Здесь можно обсудить заметки и пообщаться с другими подписчиками.

    https://t.me/sea_plus_plus_chat — official Sea++ channel chat.
    Here you can discuss notes and communicate with other subscribers.
  • Реклама

  • Sea++

    Rust в Amazon

    Rust заполучил еще одного спонсора, компанию Amazon: https://aws.amazon.com/jp/blogs/opensource/aws-sponsorship-of-the-rust-project/

    Пишут, что Амазон использует Rust в критичных к производительности компонентах Lambda, EC2 и S3.

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

    English version: https://telegra.ph/Rust-at-Amazon-10-15
  • Sea++

    CURL — это C

    Интересное рассуждение автора библиотеки libcurl Дэниела Стенберга на тему выбранного для проекта языка C https://daniel.haxx.se/blog/2017/03/27/curl-is-c/

    Главная идея: проект использует стандарт C89 для совместимости практически со всеми ОС и устройствами, все знают этот язык, переписывание на Rust дало бы огромное количество багов, которых нет сейчас, новые баги перимущественно возникают из-за логических ошибок в коде, а не по причине небезопасности языка.

    Возможно, автоматические утилиты преобразования в unsafe Rust код помогли бы тут.

    English version: https://telegra.ph/CURL-is-C-10-11
  • Sea++

    Комментарии (comments)