我在运行使用-xSSE4.1 compilation-flag构建的可执行文件时遇到分段错误。我在支持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枚举为short int。
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
给我一个分段错误。
在执行第6行之前,$ r10的值为0x7fffd4f22fe0
;这是一个16字节对齐的地址,因此第6行执行没有问题。但是第7行从(0x7fffd4f22fe0 + 0x22)
地址加载,该地址不是16字节对齐的。
此外,gdb将&ps_mv_refine_ctxt->i2_tot_cost[0][0]
的值打印为0x7fffd4f22fe0
,即$ r10。
我关注的是前两个_mm_loadu_si128
在 movdqu 时被转换为 movdqa 的原因。
当我使用-xSSE4.2或-xAVX编译标志构建时,相同的可执行文件,所有四条_mm_loadu_si128指令都被转换为 movdqu ,因此没有问题。此问题仅在release-build(-O3标志)中可见。
我正在使用英特尔C / C ++编译器。我觉得__declspec(align(16))
在结构定义中是不必要的。但它不会导致这种奇怪的行为(通过删除它来测试并发现行为没有变化)。
对不起,很长的帖子。认为这些细节是必要的。