我在 C 中有一个原型(prototype)为 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);
}
正如所怀疑的那样,您遇到了对齐问题。
如果您没有正确对齐数据,或者使用函数在未对齐的地址加载和存储,结果就是崩溃。
如果你想使用未对齐的地址,那么这个问题就解决了:
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()功能。
我是一名优秀的程序员,十分优秀!