Пусть vptr будет указателем на vtable, который переносится по объектам
чьи классы подчиняются виртуальным функциям.
Изменение vptr, скорее всего, не является предполагаемым поведением.
Однако такие изменения не могут быть обнаружены как незаконные
доступ к памяти, так как указатель находится в границах
выделенная память. «Efence» и «valgrind / memcheck» не будут
помощь — насколько мне известно.
Тем не менее, непреднамеренное изменение vptr может привести к серьезным проблемам.
Если vptr изменяется, чтобы указать на произвольную память, тогда удаление
Оператор может вызвать немедленную ошибку сегментации.
Есть ли что-нибудь, что может установить ‘стражу’ на vtables, или
на указатели на vtables, так что любое изменение отслеживается?
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
Обнаруживает нарушение по вызову на «виртуальный ~ 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 всех объектов.
Задача ещё не решена.
Других решений пока нет …