Re[5]: Как удаляется vptr?
От: rg45 СССР  
Дата: 11.04.23 09:24
Оценка: +1
Здравствуйте, avovana, Вы писали:

A>Теперь ответьте, пожалуйста, дорогому интервьюеру:


A>
A>"Где находится vptr у созданного объекта. И утечёт ли он, если деструктор базового класса невиртуальный?"
A>int main(void) { 
A>    Base* base = new Derived; 
    base->>basePrint(); 
A>    delete base; 
A>    return 0; 
A>}
A>

A>На 1ый вопрос, как понял, вы уже ответили — что это компилятор-specific. И что, в принципе, согласны, что может быть реализация, что vptr один для всех. И может хранится в базовом классе. И на какую таблицу вирт методов он указывает зависит от того какие конструкции сделал компилятор и как ими пользуется программа в run-time имея тип текущего this на руках. Тогда на 2ой логично ответить, что поскольку vptr — член базового класса, то ничего страшного в delete base не произойдёт? Он "не утечёт"?

Ну для начала я бы уточнил у интервьюера, какой смысл он вкладывает в выражение "vptr утечет". Если мы считаем, что vptr — это просто указатель, то как он может утечь? "Течет" память, выделенная под данные, на которые указывает укажатель. А указатель — это просто переменная, расположенная внутри объекта, в которой хранится адрес. Утечь она может только вместе с памятью, выделенной под объект.

Потом, как я уже писал, выражение delete base порождает неопределенное поведение. Что произойдет дальше, не знает никто — в этом суть неопределенного поведения. Что куда утечет — об этом можно только фантазировать.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[4]: Как удаляется vptr?
От: avovana Россия  
Дата: 11.04.23 09:29
Оценка:
Здравствуйте, cppguard, Вы писали:

C>Если прямо вот такой дословный вопрос, то я бы собрался и ушёл с собеседования. Опыт говорит, что даже за большие деньги с мудаками лучше не работать — нервы потом лечить дороже выйдет.


Мне рассказали, что у них общий набор. То есть, кандидат собеседуется по этапам. Ему ставят оценки. Потом кандидатуру выставляют на внутреннем портале. Команды её смотрят. И если кто заинтересуется, зовут пообщаться. Рассказывают про проект.
То есть, такая воронка по отсеву/выбора the best кандидата.

И тогда вопрос — может стоит "пропустить мимо ушей" не очень адекватный вопрос, ради того, чтобы дойти до конца? Ведь совсем не факт что будешь работать именно с этим человеком в команде. Или наличие такого вопроса в процессе собеседований — чёрная метка на всю компанию?
Отредактировано 11.04.2023 9:31 avovana . Предыдущая версия . Еще …
Отредактировано 11.04.2023 9:30 avovana . Предыдущая версия .
Re[6]: Как удаляется vptr?
От: avovana Россия  
Дата: 11.04.23 09:39
Оценка:
Здравствуйте, rg45, Вы писали:

R>Ну для начала я бы уточнил у интервьюера, какой смысл он вкладывает в выражение "vptr утечет". Если мы считаем, что vptr — это просто указатель, то как он может утечь? "Течет" память, выделенная под данные, на которые указывает укажатель. А указатель — это просто переменная, расположенная внутри объекта, в которой хранится адрес. Утечь она может только вместе с памятью, выделенной под объект.


R>Потом, как я уже писал, выражение delete base порождает неопределенное поведение. Что произойдет дальше, не знает никто — в этом суть неопределенного поведения. Что куда утечет — об этом можно только фантазировать.


К примеру SaZ предложил вариант, что этот указатель будет создан левее объекта.
Как понял, у него такое удаление delete base не ub. Т.к. delete будет знать, что надо и этот vptr который левее удалить.
Вы говорите, что это ub. Можно тогда представить ситуацию, что реализация как описал SaZ, но вот поскольку вы говорите, что это ub, то delete base не заглянет для удаления в память левее объекта, где лежит этот vptr. И удалит лишь объект? Тогда те 8 байт останутся. А оперировать далее будет памятью после этих 8ми байт — т.е. пустым местом объекта после его удаления. Создаём, к примеру, новый объект. Снова 8 байт + объект. Плохо удаляем — delete base. Снова удалится только объект. Т.к. вы сказали что это ub. Вот такое ub к примеру — плохо подчищается память. Не удалился vptr. Итого уже 8,8байт|пустое место для нового объекта. Может быть такая реализация ub?
Вот и "течёт" указатель. Но течёт из-за такого варианта ub — плохо подчистили память, выделенную под объект.
Отредактировано 11.04.2023 9:41 avovana . Предыдущая версия . Еще …
Отредактировано 11.04.2023 9:41 avovana . Предыдущая версия .
Re[7]: Как удаляется vptr?
От: rg45 СССР  
Дата: 11.04.23 10:03
Оценка: +2
Здравствуйте, avovana, Вы писали:

A>К примеру SaZ предложил вариант, что этот указатель будет создан левее объекта.

A>Как понял, у него такое удаление delete base не ub. Т.к. delete будет знать, что надо и этот vptr который левее удалить.
A>Вы говорите, что это ub. Можно тогда представить ситуацию, что реализация как описал SaZ, но вот поскольку вы говорите, что это ub, то delete base не заглянет для удаления в память левее объекта, где лежит этот vptr. И удалит лишь объект? Тогда те 8 байт останутся. А оперировать далее будет памятью после этих 8ми байт — т.е. пустым местом объекта после его удаления. Создаём, к примеру, новый объект. Снова 8 байт + объект. Плохо удаляем — delete base. Снова удалится только объект. Т.к. вы сказали что это ub. Вот такое ub к примеру — плохо подчищается память. Не удалился vptr. Итого уже 8,8байт|пустое место для нового объекта. Может быть такая реализация ub?
A>Вот и "течёт" указатель. Но течёт из-за такого варианта ub — плохо подчистили память, выделенную под объект.

UB обусловлено в первую очередь тем, что будет вызвана неполная цепочка деструкторов всех подобъектов, входящих в состав полного объекта. И это касается не только подобъектов, связанных друг с другом отношением наследования, но также и подобъектов инкапсулированных внутри этих подобъектов. Ведь в составе членов-данных могут находиться не только простые типы, но и тимы со сложным конструированием и разрушением. Даже если память, выделенная полному объекту корректно удалится вместе с vptr, как бы он нибыл реализован, все равно данный сценарий квалифицируется стандартом как порождающий неопределенное поведение. И что произойдет дальше — рассуждать об этом можно или по незнанию, или с целью провокации собеседуемого кандидата.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[7]: Как удаляется vptr?
От: Stanislav V. Zudin Россия  
Дата: 11.04.23 10:03
Оценка: +1
Здравствуйте, avovana, Вы писали:

A>К примеру SaZ предложил вариант, что этот указатель будет создан левее объекта.

A>Как понял, у него такое удаление delete base не ub. Т.к. delete будет знать, что надо и этот vptr который левее удалить.
A>Вы говорите, что это ub. Можно тогда представить ситуацию, что реализация как описал SaZ, но вот поскольку вы говорите, что это ub, то delete base не заглянет для удаления в память левее объекта, где лежит этот vptr. И удалит лишь объект? Тогда те 8 байт останутся.

Если так рассуждать, то ub может отформатировать диск
Теоретически может. На деле всё гораздо прозаичнее. Да, деструктор производного класса не вызовется и не выполнит свои обязанности.
Но память, выделенная манагером памяти объекту, освободится. В том же объеме, в каком было выделено. А что уж там лежало, указатель на vtbl, данные производного класса — это манагеру памяти до лампады.
_____________________
С уважением,
Stanislav V. Zudin
Re[5]: Как удаляется vptr?
От: Stanislav V. Zudin Россия  
Дата: 11.04.23 10:07
Оценка: -1
Здравствуйте, avovana, Вы писали:

SaZ>>Таким образом указатель на таблицу будет лежать по отрицательному смещению и к нему легко достучаться. Но при освобождении памяти всё корректно удалится, блок памяти то целостный и компилятор будет знать о факте наличия этого самого vptr по типу базового класса.


A>И тогда, получается, не важно виртуальный ли деструктор у базового класса. Когда будем удалять этот объект — delete base будет знать об этом header'e(с виртуальным указателем) лежащим левее/выше и спокойно его удалит?


Да.
_____________________
С уважением,
Stanislav V. Zudin
Re[4]: Как удаляется vptr?
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 11.04.23 11:36
Оценка:
Здравствуйте, koenjihyakkei, Вы писали:

K>Вопрос про виртуальный деструктор это больше про junior

Проблема в том, что на вакансии синеёров приходят джуны и мидлы.
Sic luceat lux!
Re[4]: Как удаляется vptr?
От: koenjihyakkei Россия  
Дата: 11.04.23 11:46
Оценка: 1 (1)
Здравствуйте, Marty, Вы писали:

M>Вообще интересно. А куда стукнуть? Я б тоже сходил. В крайнем случае — принесу ещё ржаки на форум


Легко же ищется: https://www.tinkoff.ru/career/it/?internal_source=profpage_about&tagsUrl=c
Re[3]: Как удаляется vptr?
От: sergii.p  
Дата: 11.04.23 12:51
Оценка: -1
Здравствуйте, avovana, Вы писали:

A>2) И был вопрос про "утечёт ли vptr Derived'а если delete base; И деструктор базового класса не виртуальный."


вопрос немного не корректен. Но очень похоже на классический вопрос про виртуальный деструктор. И на него получается надо отвечать: "утечёт".
Re[5]: Как удаляется vptr?
От: flаt  
Дата: 11.04.23 14:30
Оценка: +1
Здравствуйте, avovana, Вы писали:

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

Стоит или не стоит с таким работать — зависит от кучи условий и общего климата в команде и компании вообще. Возможно, сработаетесь. Или ты окажешься умнее его и продвинешься быстрее/выше. Или он окажется феерическим мудаком и заколебает своей звёздной тупостью тебя и остальных.

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

A>Мне рассказали, что у них общий набор. То есть, кандидат собеседуется по этапам. Ему ставят оценки. Потом кандидатуру выставляют на внутреннем портале. Команды её смотрят. И если кто заинтересуется, зовут пообщаться. Рассказывают про проект.


Сразу лесом.

Суть в том, что кандидат оказывается сразу в заведомо неравном положении и его просеивают сквозь туеву хучу интервью и этапов, ничего не давая взамен — ни чёткого плана процесса найма, ни информации о команде и проектах, ни полного списка плюшек и компенсации (кроме условного "300к синьору" и то не факт). В итоге ты теряешь много времени и нервов, а потом ждёшь рассмотрения неизвестное количество времени, пока они смотрят других кандидатов.

На такое стоит идти только ради FAANG и/или большой зарплаты. Ну, или если скучно и в фоне закинул им резюме с целью "вдруг возьмут, а на месте разберёмся". Но 300к — это начальный уровень синьора, в среднем, поэтому идти на подобную потогонку к ним на не самую хорошую зарплату ну никакого смысла нет.
Re[5]: Как удаляется vptr?
От: SaZ  
Дата: 11.04.23 14:53
Оценка:
Здравствуйте, avovana, Вы писали:

A>И тогда, получается, не важно виртуальный ли деструктор у базового класса. Когда будем удалять этот объект — delete base будет знать об этом header'e(с виртуальным указателем) лежащим левее/выше и спокойно его удалит?


Нет. Объявление деструктора виртуальным — это явное указание компилятору о том что надо идти по всей таблице и дёргать каждый деструктор. Такой оверхед не всегда нужен. У меня даже на практике был случай, когда все деструкторы были пустые не смотря на наличие виртуальных методов — для скорости их можно было пропустить не смотря на предупреждения. Но в большинстве случаев отсутствие виртуальных деструкторов при полиморфизме это либо антипаттерн, либо осознанный грязный хак.
Предположу, что в С++03 и младше отсутствие виртуального деструктора можно рассматривать как аналог final, то есть пометку, что класс спроектирован без возможности наследования.
Re[4]: Как удаляется vptr?
От: SaZ  
Дата: 11.04.23 14:55
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>Здравствуйте, avovana, Вы писали:


A>>2) И был вопрос про "утечёт ли vptr Derived'а если delete base; И деструктор базового класса не виртуальный."


SP>вопрос немного не корректен. Но очень похоже на классический вопрос про виртуальный деструктор. И на него получается надо отвечать: "утечёт".


Память самого объекта не утечёт. Утечь могут лишь ресурсы, которые нужно явно освобождать в деструкторе, например открытые файлы.
Re[6]: Как удаляется vptr?
От: qaz77  
Дата: 11.04.23 15:10
Оценка: +1
Здравствуйте, SaZ, Вы писали:
SaZ>Но в большинстве случаев отсутствие виртуальных деструкторов при полиморфизме это либо антипаттерн, либо осознанный грязный хак.

Для чисто абстрактных классов (ака интерфейсов) не всегда нужно наличие виртуального деструктора.
Если не предполагается удаление экземпляра через delete указателя на этот интерфейс, т.е. удаление не входит в перечень поддерживаемых интерфейсом операций.

Сейчас не вспомню точно, в какой-то старой книжке по C++ (то ли Саттера, то ли Мейерса), было правило, что в базовом полиморфном классе деструктор должен быть или public virtual или protected non-virtual.

Вот для интерфейсов подход с protected non-virtual вполне нормален ИМХО.

class IPrintable
{
public:
  virtual void print() = 0;

protected:
  ~IPrintable() = default; 
};

class Impl final: public IPrintable
{
public:
  virtual void print() override { /*...*/ }
};

void main()
{
   Impl im;

   IPrintable* p = &im;
   p->print();
   delete p; // фигушки
}
Re[5]: Как удаляется vptr?
От: avovana Россия  
Дата: 11.04.23 18:23
Оценка:
Здравствуйте, koenjihyakkei, Вы писали:

M>>Вообще интересно. А куда стукнуть? Я б тоже сходил. В крайнем случае — принесу ещё ржаки на форум

K>Легко же ищется: https://www.tinkoff.ru/career/it/?internal_source=profpage_about&tagsUrl=c

Если интересно, можем собраться, проведу такой собес) Все примеры кодов я записал. И помню как интервьювер задавал вопросы. Сможете оценить как сейчас оценивают С++сников)
Re[7]: Как удаляется vptr?
От: wander  
Дата: 11.04.23 19:12
Оценка: 12 (1) +1
Здравствуйте, avovana, Вы писали:

A>Как понял, у него такое удаление delete base не ub.

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

A>Вы говорите, что это ub.

Это не он говорит, а стандарт C++.

In a single-object delete expression, if the static type of the object to be deleted is not similar ([conv.qual]) to its dynamic type
and the selected deallocation function (see below) is not a destroying operator delete, the static type shall be a base class of the
dynamic type of the object to be deleted and the static type shall have a virtual destructor or the behavior is undefined
.
In an array delete expression, if the dynamic type of the object to be deleted is not similar to its static type, the behavior is undefined.

https://eel.is/c++draft/expr.delete#3
Re: Как удаляется vptr?
От: Максим Россия  
Дата: 12.04.23 18:27
Оценка: 1 (1)
A>Где есть вообще этот vptr?

Неплохая серия статей на данную тему. Можно повторить опыты из статьи на своем железе/компиляторе и посмотреть как оно у Вас устроенно.
https://shaharmike.com/cpp/vtable-part1/
Errare humanum est
Re[6]: Как удаляется vptr?
От: avovana Россия  
Дата: 13.04.23 18:27
Оценка:
Здравствуйте, flаt, Вы писали:

F>Судя по этой теме, в рантайме языка ты тоже не разбираешься, иначе поправил бы сразу или уточнил бы у собеседующего, на худой конец. Это не страшно, всегда можно научиться, если есть желание.


Спасибо за поддержку. На самом деле подготавливался. Этот вопрос с vptr изрядно меня запутал. Не каждый день встречаешь размышления про delete base и судьбе vptr в этой связи) Интервьюер ещё по разному вокруг этой темы ходил. После обсуждений здесь в топике стало больше понятного насчёт vptr, возможной имплементации, ub.

И что ты думаешь? Сегодня на собеседование в касперском меня снова спросили про этот виртуальный указатель)
На этот раз я уже подготовленный отвечал)
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.