我在C中有一个带有原型void f(__m128i *x)
的函数。在此函数中,我现在调用_mm_shuffle_epi8(*x, MASK)
,其中MASK
是常量__m128i
类型。当我运行代码时,我得到一个分段错误,Valgrind发现它实际上是在这一行上发生的一般保护错误。
这可能是什么原因,我该如何解决这个问题?
小工作示例:
#include <wmmintrin.h>
#include <smmintrin.h>
#define BSWAP_MASK _mm_set_epi8(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
#define ALIGN(n) __attribute__ ((aligned(n)))
static inline void g(const unsigned char *in, unsigned char *out) {
__m128i tmp = _mm_load_si128 ((__m128i*)in);
_mm_store_si128((__m128i*)out, tmp);
}
void f(__m128i *res) {
g((unsigned char*)&res, (unsigned char*)&res);
*res = _mm_shuffle_epi8(*res, BSWAP_MASK);
}
int main() {
ALIGN(16) __m128i x = _mm_set_epi8(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15);
f(&x);
}
答案 0 :(得分:1)
如怀疑的那样,你有对齐问题。
如果没有正确对齐数据,或者使用函数加载和存储未对齐的地址,结果就会崩溃。
如果您想使用未对齐的地址,那么这可以解决问题:
static inline void g(const unsigned char *in, unsigned char *out) {
//__m128i tmp = _mm_load_si128 ((__m128i*)in);
__m128i tmp = _mm_loadu_si128 ((__m128i*)in);
//_mm_store_si128((__m128i*)out, tmp);
_mm_storeu_si128((__m128i*)out, tmp);
}
至于链接器未能使该变量正确对齐的原因,请参阅Are stack variables aligned by the GCC __attribute__((aligned(x)))?及其中的答案。
如果您使用的是Linux,则可以使用posix_memalign()函数。