0

我正在寻找一种通过指针直接访问 vtable 的方法,并遇到了这篇文章: http: //www.codeproject.com/Tips/90875/Displaying-vtable-when-debugging

它工作正常,我可以通过 vtable 条目调用函数。但是我很难理解这行deo:

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

ptr是指向对象的指针。我如何破译这一行以及如何vt获得 vtable 地址?

谢谢你。

4

2 回答 2

2

_vtable 在对象中的实际位置取决于编译器。该代码假定 _vtable 地址首先存储在对象中(所有现代编译器似乎都这样做)。此外,每个类只有一个 vtable,存储在一个位置。因此,每个实例都有一个指向函数指针数组的地址。

基本上,您创建了一个名为 vt 的变量,它是一个指向返回 void 且不带参数的函数的指针数组。然后用对象的第一个成员(vtable 的地址)中找到的内容初始化这个变量。

(void (***)())ptr

意味着您将第一个 4(32 位机器)或 8(64 位机器)转换为一个指向函数指针数组的指针,该数组返回 void 并且不带参数。

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

返回这 4 或 8 个字节的内容,即 vtable 的地址。

于 2014-12-06T12:16:35.493 回答
1

void (**vt)()
vt 是指向某个函数的指针的指针。此函数返回 void 并且不接受任何参数。
void (***)()
表示指向指向此类函数的指针的指针(即,比上面多一个指针级别)。

首先,您将 ptr 转换为这样的三级函数指针。
然后,你得到它指向的东西(用 single *),这是一个两级指向函数的指针,即。相同类型的变量 vt。这意味着您可以将它分配给 vt,而这正是这条线的作用。

为什么?

指向 void-no-param-function 的单个函数指针可以存储在这样的变量 x:void(*x)()中。并且不完全相关,如果你想将一些数组传递给一个函数,你正在传递一个指针。IE。将数组地址存储在指针中以访问整个数组就足够了(如果长度已知)。
这意味着void(**vt)()可以存储(地址)一个函数指针数组。
vtable 不是别的,只是一个函数指针数组。

如果您有一个带有一些变量(例如颜色和 vtable)的 Car 类,并且它使用例如。每个对象 200 字节。指向汽车的指针就像指向 200 字节数组的指针,如果您在代码中访问颜色,编译器会查找该颜色位于例如。字节 133 并生成对其的访问。

vtable 在这个对象中的位置是实现定义的,但通常是在开始时。如果你有一个指向汽车的指针,它是一个指向 200 字节数组的指针,首先分为一些函数指针,然后是一些其他数据......

=> vtable,即。函数指针数组,从汽车的起始地址开始。
=> 如果您将汽车指针转换为指向 vtable 的指针,即。指向“函数指针数组”的指针,即。指向“指向函数的指针”的指针并尊重这一点,你有 vtable 数组。

于 2014-12-06T12:18:32.560 回答