Информация об изменениях

Сообщение Re[3]: Как удаляется vptr? от 10.04.2023 20:29

Изменено 10.04.2023 20:41 rg45

Re[3]: Как удаляется vptr?
Здравствуйте, avovana, Вы писали:

A>То есть правильно здесь представили что vptr лишь у базового. И наследники как-будто бы его наследуют?


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

A>
A>class Base
A>{
A>public:
A>    FunctionPointer* __vptr;
A>    virtual void function1() {};
A>    virtual void function2() {};
A>};

 
A>class D1: public Base
A>{
A>public:
A>    virtual void function1() {};
A>};
 
A>class D2: public Base
A>{
A>public:
A>    virtual void function2() {};
A>};
A>

A>https://radioprog.ru/post/1279
A>Тогда в случае не виртуального деструктора у базового класса как в топикстарте — "vptr не будет утекать". Интервьюер всё пытался понять от меня — будет ли он утекать или нет) Просто если у каждого он свой:
A>у base
A>у derived
A>то ведь если
A>
A>Base *obj = new Derived // без virtual dtor
A>delete obj
A>

A>То что будет с Derived vptr?

Я думаю, что по этой ссылке просто картинка неудачная, хотя на словах все написано правильно:

Компилятор также добавляет член скрытого указателя к самому базовому классу, который использует виртуальные функции. Хотя компилятор делает это автоматически, покажем в следующем примере, куда он добавляется:

Смысл же в том, чтоб, имея один только указатель на Base, мы могли бы найти таблицы виртуальных функций любых производных классов. Как это можно сделать, если дополнительная информация, необходимая для поиска таблиц, (которую мы условно называем vptr), не будет доступна через Base?

Ну и главное, данный сценарий порождает неопределенное поведение. Что будет дальше, не знает никто! Вот так и нужно было ответить.
Re[3]: Как удаляется vptr?
Здравствуйте, avovana, Вы писали:

A>То есть правильно здесь представили что vptr лишь у базового. И наследники как-будто бы его наследуют?


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

A>
A>class Base
A>{
A>public:
A>    FunctionPointer* __vptr;
A>    virtual void function1() {};
A>    virtual void function2() {};
A>};

 
A>class D1: public Base
A>{
A>public:
A>    virtual void function1() {};
A>};
 
A>class D2: public Base
A>{
A>public:
A>    virtual void function2() {};
A>};
A>

A>https://radioprog.ru/post/1279
A>Тогда в случае не виртуального деструктора у базового класса как в топикстарте — "vptr не будет утекать". Интервьюер всё пытался понять от меня — будет ли он утекать или нет) Просто если у каждого он свой:
A>у base
A>у derived
A>то ведь если
A>
A>Base *obj = new Derived // без virtual dtor
A>delete obj
A>

A>То что будет с Derived vptr?

Я думаю, что по этой ссылке просто картинка неудачная, хотя на словах все написано правильно:

Компилятор также добавляет член скрытого указателя к самому базовому классу, который использует виртуальные функции. Хотя компилятор делает это автоматически, покажем в следующем примере, куда он добавляется:

Смысл же в том, чтоб, имея один только указатель на Base, мы могли бы найти таблицы виртуальных функций любых производных классов. Как это можно сделать, если дополнительная информация, необходимая для поиска таблиц, (которую мы условно называем vptr), не будет доступна через Base?

Ну и главное, данный сценарий порождает неопределенное поведение. Что будет дальше, не знает никто! Вот так и нужно было ответить.

P.S. В простейшей реализации виртуального механизма, которую можно себе представить, на любую из таблиц виртуальных функций могут одновременно ссылаться множество объектов. Эти объекты появляются и исчезают, появляются и исцезают, а таблица остается в памяти неизменной. Когда освободится память занимаемая таблицей? Опять же, достоверно это знает только компилятор, но вероятно, при завершении программы. И память занимаемую таблицей будет освобождать код, сгенерированный компилятором (если освобождение вообще требуется как таковое). Так что даже если при освобождении какого-то из объектов произошла утечка памяти. то это вряд ли занимаемая виртуальной таблицей. Ну и повторюсь, после того, как программа породила UB, все дальнейшие прогнозы того, что произойдет дальше просто некорректно.