将未分配内存中的Derived*
静态转换为Base*
时,gcc的ASAN报告:
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在此处报告无效的读取权限?不应该指针偏移,因此在编译时可以知道正确的结果指针值吗?
那为什么这个读取访问权限甚至是必要的呢?
答案 0 :(得分: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抱怨因为你试图访问一些导致段错误的随机内存地址。