运行使用 -xSSE4.1 编译标志构建的可执行文件时出现分段错误。我在支持 SSE4.1、SSE4.2 和 AVX 的机器上运行它。
导致分段错误的内在函数:
m_best_cost_0 = _mm_loadu_si128((__m128i *) &ps_mv_refine_ctxt->i2_tot_cost[0][0]);
m_2nd_best_cost_0 = _mm_loadu_si128((__m128i *) &ps_mv_refine_ctxt->i2_tot_cost[1][0]);
m_best_mv_cost_0 = _mm_loadu_si128((__m128i *) &ps_mv_refine_ctxt->i2_mv_cost[0][0]);
m_2nd_best_mv_cost_0 = _mm_loadu_si128((__m128i *) &ps_mv_refine_ctxt->i2_mv_cost[1][0]);
结构定义:
typedef struct
{
__declspec(align(16)) WORD16 i2_tot_cost[2][TOT_NUM_PARTS];
__declspec(align(16)) WORD16 i2_mv_cost[2][TOT_NUM_PARTS];
}mv_refine_ctxt;
TOT_NUM_PARTS 是一个值为 17 的枚举,而 WORD16 是一个短整数。
gdb 中的“layout asm”命令显示了被转换为的内在代码段:
1 ¦0x5cbfec <hme_calc_sad_and_result_num_part_lt_9+108> mov 0x98(%rdi),%r11 ¦
2 ¦0x5cbff3 <hme_calc_sad_and_result_num_part_lt_9+115> mov 0x20(%r12),%r14 ¦
3 ¦0x5cbff8 <hme_calc_sad_and_result_num_part_lt_9+120> movslq 0x14(%r12),%rdx ¦
4 ¦0x5cbffd <hme_calc_sad_and_result_num_part_lt_9+125> movslq %eax,%rax ¦
5 ¦0x5cc000 <hme_calc_sad_and_result_num_part_lt_9+128> movslq %r15d,%r15 ¦
6 ¦0x5cc003 <hme_calc_sad_and_result_num_part_lt_9+131> movdqa (%r10),%xmm2 ¦
7 >¦0x5cc008 <hme_calc_sad_and_result_num_part_lt_9+136> movdqa 0x22(%r10),%xmm7 ¦
8 ¦0x5cc00e <hme_calc_sad_and_result_num_part_lt_9+142> movdqu 0x50(%r10),%xmm11 ¦
9 ¦0x5cc014 <hme_calc_sad_and_result_num_part_lt_9+148> movdqu 0x72(%r10),%xmm6
第 7 行:
0x5cc008 <hme_calc_sad_and_result_num_part_lt_9+136> movdqa 0x22(%r10),%xmm7
给我一个分段错误。
$r10 的值0x7fffd4f22fe0
就在执行第 6 行之前;这是一个 16 字节对齐的地址,因此第 6 行执行没有问题。但是第 7 行是从地址加载的,(0x7fffd4f22fe0 + 0x22)
该地址不是 16 字节对齐的。gdb 也打印&ps_mv_refine_ctxt->i2_tot_cost[0][0]
as 0x7fffd4f22fe0
which is $r10 的值。
我担心的是为什么前两个在应该是 movdqu 的时候被_mm_loadu_si128
翻译成movdqa。
当我使用 -xSSE4.2 或 -xAVX 编译标志构建相同的可执行文件时,所有四个 _mm_loadu_si128 指令都被转换为movdqu,因此没有问题。此外,该问题仅在 release-build (-O3 标志)中可见。
我正在使用英特尔 C/C++ 编译器。我觉得__declspec(align(16))
结构定义中没有必要。但它不会导致这种奇怪的行为(通过删除它进行测试,发现行为没有变化)。
对不起,很长的帖子。认为这些细节是必要的。