Магистерский курс C++ (МФТИ, 2022-2023). Лекция 15. Аллокаторы

preview_player
Показать описание
Лекции в магистратуре МФТИ по современному C++ на русском языке. Кафедра микропроцессорных технологий.

На этой лекции мы пройдём вместе с человечеством путь к аллокаторам принятым в стандарте C++11 и C++14. Сначала мы рассмотрим глубокие корни аллокаторов а дальше двинемся вперед к сложным проблемам и сложным концепциям. И в конце, увы, придём в своего рода тупик. Но такова жизнь.

Лектор: Константин Владимиров.
Дата лекции: 8 февраля 2023 года.
Съёмка и звук: Юлий Тарасов.

Timeline:
00:00 Аллокаторы в языке C
07:27 Аллокаторы Степанова
14:11 Проблемы ранних аллокаторов
21:57 Weasel words
31:45 C++11 спешит на помощь
37:23 Case study: free list
58:48 Пропагация аллокаторов
01:03:57 Локальные аллокаторы
01:14:35 Проблема scoped аллокатора

Errata:
* тут пока пусто
Рекомендации по теме
Комментарии
Автор

Как всегда - ясно, просто и великолепно

pompei
Автор

47:00 Константин, здесь явно UB. Предположим, что в deallocate пришел указатель T *, который в действительности указывает на объект типа T. Тогда reinterpret_cast<node *>(ptr) даст указатель node *, который всё ещё указывает на объект типа T, строго по правилам преобразования указателей ([basic#compound-5], [expr.reinterpret.cast#7], Да и в принципе, если значение указателя не "указывает на что-то, pointer-interconvertible с node", оно останется неизменным, только тип поменяется. В следующей строке (88) мы сразу делаем обращение к объекту (node), не являющегося type-accessible [expr#basic.lval-11], получая UB

Первым шагом к исправлению было бы заменить aligned_storage (который с С++23 deprecated), на T. Тогда, если гарантировать, что в deallocate приходят только указатели, выделенные аллокатором, благодаря pointer-interconvertible сможем получать указатель на node
Вторым шагом было бы заменить выделение блока памяти на массив из node, чтобы сразу начать жизнь объектов node. Это просто сделать, добавив полю next инициализатор, сделав union implicit-lifetime type

Скорее всего нужно будет сделать еще что, но для этого нужно более подробно шерстить стандарт. Ну и разумеется, всё ещё ждём завоза в компиляторы std::start_lifetime_as и std::is_implicit_lifetime

ddvamp
Автор

Я правильно понимаю, что можно для небольших размеров контейнера можно сделать кастомную арену и кастомные указатели размером 8-16-32 бита? На каких-нибудь списках и деревьях, где указатели занимают много места, так можно неплохо сэкономить память:)

Alamat
Автор

А на вопрос про gcc и list на 56:00 есть ответ?
Ведет себя очень странно, когда вызывается list.remove gcc создает аллокатор инта из аллокатора ноды, потом создает аллокатор ноды из аллокатора инта, и видимо после ремува удаляет аллокатор с вынутой нодой.

Dooezzz
Автор

Константин, спасибо за лекции! Можете, пожалуйста, разъяснить почему надо использовать aligned_storage а не просто написать union node {
node *next;
T storage;
};

rodionmontsarj
Автор

51:29
У нас всегда условие this == &other будет true, мы в операторе сравнения это явно указали, и мы никогда ничего не мувнем. Может быть лучше листы сравнивать?

danielkeehl
Автор

1:27:00 -- тут думаю холиварный вопрос про то, -- надо ли считать контейнеры с различными способами выделения памяти неэквивалентными (неравными)?

safocl
Автор

почему statefull аллокаторы совсем не копируются при присваивании, почему нельзя сделать глубокую копию?

МарияВе-рэ
Автор

1:10:40 -- думаю gcc прав тут -- поскольку метод const arena_type& arena() выглядит как конструктор, однако с возвращаемым типом.

safocl
Автор

1:10:00 Константин, правильно ли я понимаю, что здесь срабатывает "A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the
completed scope of S. No diagnostic is required for a violation of this rule" из С++20 и "The result of the search is the declaration set of S(M, T). If it is an invalid set, the program is ill-formed. If it differs from the result of a search in T for M in a complete-class context ([class.mem]) of T, the program is ill-formed, no diagnostic required." из С++23?
Если это так, за что же балл обещался?)

ddvamp
Автор

Меня смущает, что для указателей используется static_cast, вместо reinterpret_cast.

Alexander_Gurov_RF
Автор

Подскажите, пожалуйста, как вы называете конструктор с U, коэршен конструктор (типа когерентный, как на английском это пишется)?

DrUlrih
Автор

- видимо, нет проверки на this == &rhs ?

alex_s_ciframi
Автор

28:00 но ведь если в 98 году в аллокаторе были запрещены иные typedef'ы, то как тогда они должны были возвращать far pointer'ы вектору? для них ведь отдельный тип заведён, а вы как раз раньше говорили, что их поддержка это единственная причина, по которой Степанов их изобрёл

sigasigasiga
Автор

23:40 а можете, пожалуйста, объяснить зачем это вообще было нужно добавлять? разве стандарт предусматривает какие-то другие способы вызвать конструктор? у меня есть догадка, что placement new не работал с far pointer'ами, но я не уверен насколько эта догадка верна

sigasigasiga