简体   繁体   中英

C++: Help understanding this line of code

I was looking for a way to access the vtable directly through a pointer and came across this post: http://www.codeproject.com/Tips/90875/Displaying-vtable-when-debugging

It works fine and I can invoke functions through the vtable entries. But I'm having trouble understanding this line of deo:

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

ptr is a pointer to an object. How can I decipher this line and how does vt get the vtable address?

Thank you.

The actual location of the _vtable in an object is compiler dependant. The code assumes that the _vtable address is stored first in the object (which all modern compilers seem to do). Also, there is only one vtable per class, which is stored in a single location. Thus, every instance has an address to that array of pointers to functions.

Basically, you create a variable named vt, that is an array of pointers to functions that return void and take no parameters. Then you initialize this variable with the content found in the first member of the object (the adress of the vtable).

(void (***)())ptr

means that you cast this first 4 (32 bit machine) or 8 (64 bit machine) to a pointer to an array of function pointers that return void and take no parameters.

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

returns the content of those 4 or 8 bytes, that is the address of the vtable.

void (**vt)()
vt is a pointer to a pointer to some function. This function returns void and takes no parameters.
void (***)()
means a pointer to pointer to pointer to such a function (ie. one pointer level more than above).

First, you´re casting ptr to such a three-level-pointer-to-function.
Then, you get the thing it points to (with the single * ), that is a two-level-pointer-to-function, ie. the same type a the variable vt. That means you can assign it to vt, and that´s exatcly what this line does.

And why?

A single function pointer to a void-no-param-function can be stored in such a variable x: void(*x)() . And not exactly related, if you want to pass some array to a function, you´re passing a pointer. Ie. it´s enough to store the array address in a pointer to access the whole array (if the length is known).
That means void(**vt)() can store (the address of) an array of function pointers.
The vtable is nothing else, just an array of function pointers.

If you have a class Car with some variables like color and a vtable, and it uses eg. 200 byte per object. A pointer to a car is like a pointer to a 200-byte array, and if you access color in the code, the compiler looks up that color is at eg. byte 133 and generates an access to it.

Where the vtable is within this object is implementation defined, but often at the beginning. If you have a pointer to a car, it´sa pointer to a array of 200 byte, separated into some fucntion pointers first and some other data after them ...

=> The vtable, ie. an array of function pointers, starts at the start address of the car.
=> If you cast a car pointer to a pointer to vtable, ie. pointer to "function pointer array", ie. pointer to "pointer to pointer to function" and deference that, you have the vtable array.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM