我使用__int128作为struct的成员。它与-O0 (无优化)一起工作。
但是,如果启用优化(-O1),则会导致段故障崩溃。
它在指令movdqa崩溃,这需要变量对齐16。而地址由malloc()分配,只有8对齐。
我试图通过-mno-sse禁用SSE优化,但它无法编译:
/usr/include/x86_64-linux-gnu/bits/stdlib-float.h:27:1: error: SSE register return with SSE disabled那么,如果我想同时使用__int128和-O1,我能做什么呢?
提前感谢吴
顺便说一句,如果__int128只在堆栈上使用(而不是在堆上),似乎没问题。
====编辑====
很抱歉我没说真话。
事实上,我没有使用malloc()。我使用了一个内存池库,它返回按8对齐的地址。我说malloc()只是为了使事情变得简单。
测试后,我知道malloc()对齐率为16,而__int128成员在struct中也对齐16。
所以问题是我的内存池库只存在。
非常感谢。
发布于 2018-09-27 08:17:45
对于x86-64系统V,alignof(max_align_t) == 16因此malloc总是返回16字节对齐指针.听起来你的分配器坏了,如果用在long double上也会违反ABI。(将此重新发布为一个答案,因为事实证明这是答案)。
malloc返回的内存保证能够容纳任何标准类型,因此,如果大小足够大,就意味着足够对齐。
这不可能是32位代码,因为gcc不支持32位目标的__int128 .(我认为32位glibc malloc只保证8字节对齐。)实际上,在目前的系统中,alignof(max_align_t) == 16也采用32位模式.)
通常,如果您违反了类型的对齐要求,编译器就可以生成错误代码。在x86上,事情通常只处理对齐内存,直到编译器使用需要对齐的SIMD指令。即使是使用错误对齐的uint16_t*自动矢量化也可能出错(Why does unaligned access to mmap'ed memory sometimes segfault on AMD64?),所以不要假设狭窄的类型总是安全的。如果需要用C表示未对齐负载,请使用memcpy。
显然,alignof(__int128)是16岁,所以他们没有重复i386 System中的奇怪之处,即即使8字节的对象也只能保证4字节对齐,而结构化打包规则意味着编译器不能总是给它们提供自然的对齐。
这是一件好事,因为它使使用SSE进行有效的复制,并且意味着_Atomic __int128不需要任何额外的特殊处理来避免缓存行分割,这会使lock cmpxchg16b非常慢。
https://stackoverflow.com/questions/52531695
复制相似问题