令 vptr 为指向 vtable 的指针,该 vtable 与类受虚函数约束的对象一起携带。
'vptr' 的更改可能不是预期的行为。但是,这种更改不能被检测为非法内存访问,因为指针位于已分配内存的边界。'Efence' 和 'valgrind/memcheck' 无济于事——据我所知。
然而,意外的 vptr 更改可能会导致严重的问题。如果 vptr 被更改为指向任意内存,则删除运算符可能会立即导致分段错误。
是否有任何东西可以在 vtable 或指向 vtable 的指针上设置“守卫”,以便监控任何更改?
Clang++ 似乎并没有完成全部工作。给定
#include <string.h>
#include <stdio.h>
struct X { virtual ~X() {} };
int main(int argc, char** argv)
{
X x;
memset((void*)&x, 0, sizeof(X));
printf("<before exit>\n");
return 0;
}
编译并执行...
> clang++ -fsanitize=undefined -fsanitize=vptr tmp.cpp -o test
> ./test
在调用“virtual ~X()”时检测违规。
<before exit>
<unknown>: runtime error: member call on address 0xbfe30ab8 which does not point to an object of type 'X'
0xbfe30ab8: note: object has invalid vptr
74 0b e3 bf 00 00 00 00 4d 46 48 b7 74 0b e3 bf 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
^~~~~~~~~~~
invalid vptr
同样不适用于
...
X* x_p = new X();
memset((void*)x_p, 0, sizeof(X));
delete x_p;
printf("<before exit>\n");
...
vptr 损坏的检测器应该在所有对象的 vptr-s 上设置某种类型的“观察点”。