地址清理器在静态强制转换无效指针时报告错误

address sanitizer reports error when statically casting an invalid pointer

本文关键字:无效 转换 指针 错误 报告 静态 地址      更新时间:2023-10-16

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

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

指针偏移,因此不应正确生成指针 在编译时知道值?

不,虚拟继承类的偏移量在编译时是未知的,因此编译器在运行时通过访问 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 抱怨,因为您尝试访问一些导致段错误的随机内存地址。