Адресный очиститель сообщает об ошибке при статическом приведении неверного указателя
Когда статически Derived*
в нераспределенной памяти Base*
ASAN от gcc сообщает:
ASAN:DEADLYSIGNAL ================================================================= ==12829==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x563da3783776 bp 0x7ffde1670e50 sp 0x7ffde166d800 T0) ==12829==The signal is caused by a READ memory access. ==12829==Hint: address points to the zero page.
Для теста я использовал эту настройку:
struct Base2 { int dummy; };
struct Base { int dummy2; };
struct Derived : public Base2, public virtual Base { };
Derived* derived = (Derived*)0x1122334455667788; /* some pointer into non-allocated memory */
Base* base = static_cast<Base*>(derived); /* ASAN fails here */
Почему ASAN сообщает о недопустимом праве чтения здесь? Разве смещение указателя и, следовательно, правильное значение полученного указателя не должны быть известны во время компиляции?
Так почему же этот доступ для чтения вообще необходим?
1 ответ
Разве смещение указателя и, следовательно, правильное значение полученного указателя не должны быть известны во время компиляции?
Нет, смещение виртуально унаследованного класса не известно во время компиляции, поэтому компилятор вычисляет его во время выполнения, обращаясь к vtable.
Вот простой пример:
Base *foo(Derived *p) {
return static_cast<Base*>(p);
}
Компилируется в
movq (%rdi), %rax # Get vptr
addq -24(%rax), %rdi # Load offset of Base from vtable
movq %rdi, %rax # Return result
ret
ASan жалуется, потому что вы пытаетесь получить доступ к некоторому случайному адресу памяти, который вызывает ошибку.