Visual Studio — C ++: помогите понять эту строку кода

Я искал способ получить доступ к vtable напрямую через указатель и наткнулся на этот пост: http://www.codeproject.com/Tips/90875/Displaying-vtable-when-debugging

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

void (**vt)() = *(void (***)())ptr;

ptr это указатель на объект. Как я могу расшифровать эту строку и как vt получить виртуальный адрес?

Спасибо.

0

Решение

void (**vt)()
vt — указатель на указатель на некоторую функцию. Эта функция возвращает void и не принимает параметров.
void (***)()
означает указатель на указатель на указатель на такую ​​функцию (т.е. на один уровень указателя больше, чем выше).

Во-первых, вы приводите ptr к такому трехуровневому указателю на функцию.
Затем вы получите то, на что он указывает (с *), то есть двухуровневый указатель на функцию, т.е. тот же тип переменной Vt. Это означает, что вы можете назначить его vt, и это именно то, что делает эта строка.

И почему?

Одиночный указатель на функцию void-no-param-function может храниться в такой переменной x: void(*x)(), И не совсем связанный, если вы хотите передать некоторый массив в функцию, вы передаете указатель. То есть. Достаточно сохранить адрес массива в указателе, чтобы получить доступ ко всему массиву (если длина известна).
Это означает void(**vt)() может хранить (адрес) массив указателей на функции.
Vtable — это не что иное, как массив указателей на функции.

Если у вас есть класс Car с некоторыми переменными, такими как color и vtable, и он использует, например,. 200 байт на объект. Указатель на автомобиль похож на указатель на 200-байтовый массив, и если вы обращаетесь к цвету в коде, компилятор ищет, что цвет, например, равен. байт 133 и генерирует доступ к нему.

Где vtable находится внутри этого объекта, определяется реализацией, но часто в начале. Если у вас есть указатель на автомобиль, это указатель на массив из 200 байт, разделенный сначала на несколько указателей функций, а затем на некоторые другие данные …

=> Vtable, т.е. массив указателей на функции, запускается с начального адреса автомобиля.
=> Если вы приведете указатель автомобиля на указатель на vtable, т.е. указатель на «массив указателей на функции», т.е. указатель на «указатель на указатель на функцию» и, что у вас есть массив vtable.

1

Другие решения

Фактическое расположение _vtable в объекте зависит от компилятора. Код предполагает, что адрес _vtable сохраняется первым в объекте (что, похоже, делают все современные компиляторы). Кроме того, существует только один vtable на класс, который хранится в одном месте. Таким образом, каждый экземпляр имеет адрес для этого массива указателей на функции.

По сути, вы создаете переменную с именем vt, которая представляет собой массив указателей на функции, которые возвращают void и не принимают параметров. Затем вы инициализируете эту переменную содержимым, найденным в первом члене объекта (адрес виртуальной таблицы).

(void (***)())ptr

означает, что вы приведете эти первые 4 (32-битный компьютер) или 8 (64-битный компьютер) к указателю на массив указателей на функции, которые возвращают void и не принимают параметров.

*(void (***)())ptr

возвращает содержимое этих 4 или 8 байтов, то есть адрес виртуальной таблицы.

2

По вопросам рекламы [email protected]