Ho un tipo dichiarato con __attribute__((aligned(16)))
. Quando si crea con clang
su OS X su x86_64, il seguente codice causa un errore GP quando si tenta di throw
un valore contenente questo tipo. L'errore si verifica perché il compilatore genera un'istruzione di spostamento a 128 bit che deve essere allineata su un limite di 16 byte, ma l'indirizzo non è allineato correttamente.Errore di runtime Clang durante il lancio di un tipo allineato. Bug del compilatore?
Ecco un programma che riproduce il problema:
#include <stdint.h>
#include <stdio.h>
struct __attribute__((aligned(16))) int128 {
uint64_t w[2];
};
int main()
{
try {
int128 x;
throw x;
} catch (int128 &e) {
printf("%p %lu\n", &e, sizeof(e));
}
}
E lo smontaggio con la localizzazione dei guasti segnato con ->
:
a.out`main:
0x100000db0 <+0>: pushq %rbp
0x100000db1 <+1>: movq %rsp, %rbp
0x100000db4 <+4>: subq $0x40, %rsp
0x100000db8 <+8>: movl $0x10, %eax
0x100000dbd <+13>: movl %eax, %edi
0x100000dbf <+15>: callq 0x100000e8c ; symbol stub for: __cxa_allocate_exception
0x100000dc4 <+20>: movaps -0x10(%rbp), %xmm0
-> 0x100000dc8 <+24>: movaps %xmm0, (%rax)
0x100000dcb <+27>: movq 0x23e(%rip), %rsi ; (void *)0x0000000100001058
0x100000dd2 <+34>: xorl %ecx, %ecx
0x100000dd4 <+36>: movl %ecx, %edx
0x100000dd6 <+38>: movq %rax, %rdi
0x100000dd9 <+41>: callq 0x100000e9e ; symbol stub for: __cxa_throw
registro attuale:
(lldb) register read rax
rax = 0x0000000100905b08
Si guarda come quello che sta succedendo è la funzione __cxa_allocate_exception
non ha saputo sporgenza dei requisiti di allineamento del tipo per il quale sta allocando la memoria. Sul mio sistema capita di allocare un indirizzo che finisce in 8, e quindi non è allineato a 16 byte. Quando l'istruzione movaps
tenta di spostare i dati in quella posizione di memoria, la CPU si guasta a causa di un accesso non allineato.
informazioni Compiler (clang
da Xcode 6.3.2):
$ clang --version
Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
Target: x86_64-apple-darwin14.3.0
Thread model: posix
Si tratta di un bug del compilatore? Quale potrebbe essere un modo per aggirare questo problema?
UPDATE: ho presentato questo al database dei bug LLVM: https://llvm.org/bugs/show_bug.cgi?id=23868
riprodotto sulla mia macchina con clangore, ma nessun errore con GCC 4.9. Sente l'odore di un piccolo bug del compilatore poco noto ... – nneonneo
La soluzione ovvia sarebbe dichiarare il campo struct come 'uint16_t w [8]' e gestire i valori 'uint64_t' usando le funzioni dei membri accessor, se necessario. – rodrigo
@rodrigo: la struttura 'int128' nel mio esempio è in realtà la struttura' BID_UINT128' dalla [Libreria matematica virgola mobile Intel decimal] (https://software.intel.com/en-us/articles/intel-decimal -floating-point-math-library), quindi non è pratico cambiarne la definizione. –