2016-05-03 14 views
4

次のコードを考える:投げる例外はOSX 10.11.4にSIGSEGVを引き起こし+打ち鳴らす

​​

これは、GNU/LinuxとWindows上で正常に動作し、バージョン10.11の最新アップデートの前にOSX上で正常に動作するために使用します。 4。罰金は何も例外をキャッチしないので、std::terminateが呼び出されます。

しかし、clang(LLVM 7.3.0)を使用しているOSX 10.11.4では、セグメンテーションフォルトでプログラムがクラッシュします。

Program received signal SIGSEGV, Segmentation fault. 
0x0000000100000ad1 in main() at test.cpp:17 
17  throw my_exception(); 
(gdb) bt 
#0 0x0000000100000ad1 in main() at test.cpp:17 
(gdb) 

もvalgrindのはこれについて言いたいことです::スタックトレースは有用ではありません

==6500== Process terminating with default action of signal 11 (SIGSEGV) 
==6500== General Protection Fault 
==6500== at 0x100000AD1: main (test.cpp:17) 

私はコードがどのような方法で標準に違反しているとは思いません。私はここに何かを逃していますか

throwの周りにtry-catchを追加しても、SIGSEGVのためにコードがクラッシュすることに注意してください。

答えて

1

あなたが解体を見れば、あなたは一般的な保護(GP)例外はSSE movaps命令で発生していることがわかります。でも呼ばれmy_exception :: my_exception()コンストラクタの前に

 
a.out`main: 
    0x100000ad0 : pushq %rbp 
    0x100000ad1 : movq %rsp, %rbp 
    0x100000ad4 : subq $0x20, %rsp 
    0x100000ad8 : movl $0x0, -0x4(%rbp) 
    0x100000adf : movl $0x10, %eax 
    0x100000ae4 : movl %eax, %edi 
    0x100000ae6 : callq 0x100000dea    ; symbol stub for: __cxa_allocate_exception 
    0x100000aeb : movq %rax, %rdi 
    0x100000aee : xorps %xmm0, %xmm0 
-> 0x100000af1 : movaps %xmm0, (%rax) 
    0x100000af4 : movq %rdi, -0x20(%rbp) 
    0x100000af8 : movq %rax, %rdi 
    0x100000afb : callq 0x100000b40    ; my_exception::my_exception 
... 

movaps命令は、__cxa_allocate_exception(size_t)によって返されたメモリのブロックをゼロにするために使用されます。しかし、このポインタ(私の場合は0x0000000100103498)は、16バイト境界であることが保証されていません。 movaps命令のソースオペランドまたはデスティネーションオペランドがメモリオペランドの場合、オペランドは、を16バイト境界に揃えなければなりません。そうしないと、GP例外が生成されます。

問題を一時的に解決する方法の1つは、SSE命令(-mno-sse)なしでコンパイルすることです。 SSE命令はパフォーマンスを向上させることができるため、理想的なソリューションではありません。

私はこれがhttp://reviews.llvm.org/D18479に関連していると思います:

r246985は、Itaniumが_Unwind_Exceptionが並ぶ「ダブルワード」であるべきと言うと構造が正常であることを理由に、例外オブジェクトのための高いアライメントを与えるために変更を加えました__attribute__((aligned))と宣言され、16バイトのアライメントが保証されます。 libC++ abiは構造体を__attribute__((aligned))と宣言していないことが判明し、32ビットおよび64ビットプラットフォームでは8バイトのアラインメントしか保証されません。これにより、バックエンドがSIMDストア命令を発行したときに、16バイトのアラインメントが必要な場合(たとえば、movaps)、クラッシュが発生しました。

このパッチは、Darwin上でItaniumCXXABI :: getAlignmentOfExnObjectが8バイト境界整列を返してクラッシュを修正します。

..このパッチは、2016年3月31日にr264998としてコミットされました。

https://llvm.org/bugs/show_bug.cgi?id=24604https://llvm.org/bugs/show_bug.cgi?id=27208も表示されます。

更新日 Xcode 7.3をインストールしました。1(昨日リリースされた)、問題は修正されているようだ。生成されたアセンブリは、以下のようになります。

 
a.out`main: 
    0x100000ac0 : pushq %rbp 
    0x100000ac1 : movq %rsp, %rbp 
    0x100000ac4 : subq $0x20, %rsp 
    0x100000ac8 : movl $0x0, -0x4(%rbp) 
    0x100000acf : movl $0x10, %eax 
    0x100000ad4 : movl %eax, %edi 
    0x100000ad6 : callq 0x100000dea    ; symbol stub for: __cxa_allocate_exception 
    0x100000adb : movq %rax, %rdi 
    0x100000ade : movq $0x0, 0x8(%rax) 
    0x100000ae6 : movq $0x0, (%rax) 
    0x100000aed : movq %rdi, -0x20(%rbp) 
    0x100000af1 : movq %rax, %rdi 
    0x100000af4 : callq 0x100000b40    ; my_exception::my_exception 
... 
+0

グレート答え!この小さなコードがコンパイラを壊すとは思えません。パッチがすぐにプッシュされることを願って...ありがとう! – mfontanini

+1

@mfontaniniパッチがすでにプッシュされているようです。私はclang-703.0.31/Xcode 7.3.1をテストし、生成されたアセンブリはもはや 'movaps'命令を使用しません。 –

関連する問題