2013-04-03 23 views
14

kod parçası bakın.Garip Clang davranış

clang++ -o test test.cpp -std=c++11 -stdlib=libc++ 

ile derleniyor yol açar:

zsh: illegal hardware instruction ./test 

Ve

clang++ -o test test.cpp -std=c++11 -stdlib=stdlibc++ 

ile derleniyor da yol açar:

zsh: illegal hardware instruction ./test 

Clang/GCC Sürümleri:

clang version 3.2 (tags/RELEASE_32/final) 
Target: x86_64-pc-linux-gnu 
Thread model: posix 

gcc version 4.7.2 (Gentoo 4.7.2-r1 p1.5, pie-0.5.5) 

Herhangi bir öneride sorun olan nedir?

Şimdiden teşekkürler!

+9

Clang –

+0

FYI'de bir hata olduğunu söyleyebilirim, [ud2 ve clang] hakkında daha fazla bilgi (http://stackoverflow.com/q/26309300/1708801) –

cevap

5

Bu büyük olasılıkla bir argoda bir hata 3.2. Kazayı clang gövdesiyle yeniden oluşturamıyorum.

+0

Olumlu. Gövde iyi görünüyor. Yani muhtemelen clang 3.3 sabit olmalıdır. – rralf

11

Evet, bu Clang ++ 'da bir hatadır. Ben i386-pc-linux-gnu'da CLang 3.2 ile yeniden üretebilirim. Böcek işaretçisi-to-işlevine labmda dönüşüm olduğunu tespit ettik

Ve şimdi bazı rasgele analiz

...: derleyici bir tür uygun imzayla düşünebilirdi oluşturur lambda çağırır, ancak ret yerine ud2 talimatı vardır.

Muhtemelen bildiğiniz gibi ud2 talimatı, "Geçersiz Opcode" istisnasını açık bir şekilde yükselten bir talimattır. Yani, kasıtlı olarak tanımlanmamış bir talimat.

Çıkartılması bir göz atın: Yani hata minimal örnek basitçe olacak

main::$_0::__invoke(): 
     pushl %ebp 
     movl %esp, %ebp 
     subl $8, %esp 
     movl 8(%ebp), %eax 
     movl %eax, (%esp) 
     movl %ecx, 4(%esp) 
     calll main::$_0::operator()() const ; this calls to the real lambda 
     subl $4, %esp 
     ud2 ; <<<-- What the...!!! 

: tuhafı

int main() { 
    std::string(*f)() = []() -> std::string { 
     return "bla"; 
    }; 
    f(); 
    return 0; 
} 

, hata yapmaz bu thunk fonksiyonudur Dönüş türü int gibi basit bir türse, gerçekleşir. Sonra oluşturulan düşünebilirdi geçerli:

main::$_0::__invoke(): 
     pushl %ebp 
     movl %esp, %ebp 
     subl $8, %esp 
     movl %eax, (%esp) 
     calll main::$_0::operator()() const 
     addl $8, %esp 
     popl %ebp 
     ret 

Sorun dönüş değerinin yönlendirme olduğunu sanıyorum. eax gibi bir kayıt defterine sığarsa her şey iyi gider. Ancak, std::string gibi büyük bir yapı ise yığın içinde döndürülürse, derleyici karışıktır ve çaresizlik içinde ud2 yayar.

İlgili konular