静态转换无效指针时,地址清理程序报告错误

时间:2018-02-05 13:12:35

标签: c++ c++11 gcc address-sanitizer

将未分配内存中的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在此处报告无效的读取权限?不应该指针偏移,因此在编译时可以知道正确的结果指针值吗?

那为什么这个读取访问权限甚至是必要的呢?

1 个答案:

答案 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抱怨因为你试图访问一些导致段错误的随机内存地址。