Gre*_*ill 13 c++ x86-64 clang memory-alignment
我有一个声明的类型__attribute__((aligned(16))).clang在x86_64上使用OS X 构建时,以下代码在尝试throw包含此类型的值时会导致GP错误.发生故障的原因是编译器生成一个128位移动指令,该指令必须在16字节边界上对齐,但地址未正确对齐.
这是一个重现问题的程序:
#include <stdint.h>
#include <stdio.h>
struct __attribute__((aligned(16))) int128 {
uint64_t w[2];
};
int main()
{
try {
int128 x;
throw x;
} catch (int128 &e) {
printf("%p %lu\n", &e, sizeof(e));
}
}
Run Code Online (Sandbox Code Playgroud)
并且具有故障位置的拆卸标记为->:
a.out`main:
0x100000db0 <+0>: pushq %rbp
0x100000db1 <+1>: movq %rsp, %rbp
0x100000db4 <+4>: subq $0x40, %rsp
0x100000db8 <+8>: movl $0x10, %eax
0x100000dbd <+13>: movl %eax, %edi
0x100000dbf <+15>: callq 0x100000e8c ; symbol stub for: __cxa_allocate_exception
0x100000dc4 <+20>: movaps -0x10(%rbp), %xmm0
-> 0x100000dc8 <+24>: movaps %xmm0, (%rax)
0x100000dcb <+27>: movq 0x23e(%rip), %rsi ; (void *)0x0000000100001058
0x100000dd2 <+34>: xorl %ecx, %ecx
0x100000dd4 <+36>: movl %ecx, %edx
0x100000dd6 <+38>: movq %rax, %rdi
0x100000dd9 <+41>: callq 0x100000e9e ; symbol stub for: __cxa_throw
Run Code Online (Sandbox Code Playgroud)
当前注册:
(lldb) register read rax
rax = 0x0000000100905b08
Run Code Online (Sandbox Code Playgroud)
看起来正在发生的事情是__cxa_allocate_exception函数不知道它为其分配存储的类型的对齐要求.在我的系统上,它恰好分配一个以8结尾的地址,因此不是16字节对齐的.当movaps指令尝试将数据移动到该存储器位置时,CPU由于未对齐访问而发生故障.
编译器信息(clang来自Xcode 6.3.2):
$ clang --version
Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
Target: x86_64-apple-darwin14.3.0
Thread model: posix
Run Code Online (Sandbox Code Playgroud)
这是编译器错误吗?有什么方法可以解决这个问题?
更新:我已将此提交到LLVM错误数据库:https://llvm.org/bugs/show_bug.cgi?id = 23868
进一步研究一下,似乎__cxa_allocate_exception基本上从未定义过理解对齐(对于 Clang 或 GCC),因此抛出对齐的对象基本上属于 UB(好吧,对齐无论如何都是编译器特定的扩展......)。它似乎保证的唯一对齐方式是 8 字节,因为这是任何内置类型 ( double) 所需的最大对齐方式。
我能想到的最简单的解决方法就是简单地使用未对齐的类型throw:
struct unaligned_int128 {
uint64_t w[2];
unaligned_int128(const int128 &x) { w[0] = x.w[0]; w[1] = x.w[1]; }
};
int main()
{
try {
int128 x;
throw unaligned_int128(x);
} catch (unaligned_int128 &e) {
printf("%p %lu\n", &e, sizeof(e));
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
698 次 |
| 最近记录: |