2015-12-07 42 views
9

Ten kod wydawał się działać poprawnie w (ubuntu trusty) wersjach gcc i clang, aw Win 7 na VM za pośrednictwem mingw ... Niedawno uaktualniłem do Wily i kompilacje wykonane z klang crash konsekwentnie tutaj.Czy ten prosty program w języku C++ używający poprawki <locale> jest poprawny?

#include <iostream> 
#include <locale> 
#include <string> 

int main() { 
    std::cout << "The locale is '" << std::locale("").name() << "'" << std::endl; 
} 

Czasami Jego bełkot ciąg następnie Aborted: Core dumped a czasami także jej invalid free.

$ ./a.out 
The locale is 'en_US.UTF-8QX�у�X�у����0�����P�����\�(��\�(��\�(��h��t�������������y���������ț�ԛ�������en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_UP����`�������������������������p�����������@��������������`�������������p��������������������@��@��@��`��������p������������0��P��p���qp��!en_US.UTF-8QЈ[�����\�(��\�(��\�(�����������@�� �����P�����0�����P�����\�(��\�(��\�(��Ȣ�Ԣ����������������(��4��@��L��en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8!�v[��������������@�� �����P�����0�����P�����\�(��\�(���(��h��t��������������������Ȥ�Ԥ�������en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8!��[�� ����[�������7����7��.,!!x�[��!��[��!�[��@�����������@�� �����P�����0�����P�����\�(��\�(��\�(��(��4��@��L��X��d��p��|������������n_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8ѻAborted (core dumped) 

$ ./a.out 
The locale is 'en_US.UTF-8QX\%�QX\%�Q�G�0H��H�PI��I�\:|�Q\D|�Q\>|�QhK�tK��K��K��K��K��Q�K��K��K��K��K��K�en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8en_US.UTF-8ѻ 
*** Error in `./a.out': free(): invalid pointer: 0x0000000000b04a98 *** 
Aborted (core dumped) 

(Oba wyjścia programu powyżej zostały znacznie skrócone lub nie pasuje w tej kwestii).

ja też dostałem invalid free on Coliru z nim również.

Ale to jest bardzo podobny do przykładu kodu na cppreference:

#include <iostream> 
#include <locale> 
#include <string> 

int main() 
{ 
    std::wcout << "User-preferred locale setting is " << std::locale("").name().c_str() << '\n'; 
    // on startup, the global locale is the "C" locale 
    std::wcout << 1000.01 << '\n'; 
    // replace the C++ global locale as well as the C locale with the user-preferred locale 
    std::locale::global(std::locale("")); 
    // use the new global locale for future wide character output 
    std::wcout.imbue(std::locale()); 
    // output the same number again 
    std::wcout << 1000.01 << '\n'; 
} 

Właściwie że kod crashes Coliru również ...: facepalm:

Morecrashes podobnego kodu z Coliru.

Czy jest to błąd w bibliotece C++ używanej przez clang, czy ten kod jest wadliwy?

Uwaga: te awarie wydają się być ograniczone do interfejsu API w C++, jeśli użyjesz <clocale> zamiast tego, wydaje się, że wszystko działa dobrze, więc może to być po prostu banalny problem związany z powiązaniami C++?

Wariacje wykorzystujące setlocale: 123

+0

Wygląda całkiem jak błąd dla mnie. Czy rozważałeś zadawanie listy mailingowej i/lub zgłaszanie jej jako błędu? Wydaje się, że bardziej odpowiednie miejsce do pytania ... –

+0

Jeśli clang, kompilator, zawiesza się podczas kompilowania tego kodu, to jest to błąd klang, który powinien zostać zgłoszony. –

+0

@LightnessRacesinOrbit: Tak, myślę, że to jest następny krok. –

Odpowiedz

6

Wygląda to jest spowodowane libstdC++ 's zmiany ABI w swojej basic_string, co było potrzebne dla C++ 11 zgodność. Aby zarządzać tym przejściem, GCC dodał atrybut abi_tag, który zmienia zniekształconą nazwę funkcji, dzięki czemu można rozróżnić funkcje dla nowej i starej ABI, nawet jeśli zmiana nie wpłynie inaczej na zniekształconą nazwę (np. funkcjonować).

Ten kod

#include <locale> 
#include <string> 

int main() { 
    std::locale().name(); 
} 

na GCC emits a call to_ZNKSt6locale4nameB5cxx11Ev, który demangles do std::locale::name[abi:cxx11]() const i zwraca ciąg SSO z nowym ABI.

Clang, drugiej natomiast, doesn't support the abi_tag attribute i emits a call to_ZNKSt6locale4nameEv, który demangles po prostu std::locale::name() const na - co jest wersja powrocie ciąg krów (stary ABI).

Wynik netto jest taki, że program kończy się próbą użycia ciągu COW jako ciągu SSO po kompilacji z Clangiem. Powstaje Havoc.

Oczywistym rozwiązaniem jest wymuszenie starego ABI przez -D_GLIBCXX_USE_CXX11_ABI=0.

+0

Wow, to niezły pomysł! Naprawia to na moim komputerze i na coliru: http://coliru.stacked-crooked.com/a/b08f590618a7398a, http://coliru.stacked-crooked.com/a/0c769ee07e51fb02 –

1

myślę parametr "" może być coś psuje. Nie sądzę, że to argument prawny?

Aby zweryfikować to nic innego, spróbuj uruchomić to:

#include <iostream> 
#include <locale> 

int main() { 
    std::locale("").name(); 
} 
+0

To powinien być komentarz. –

1

To kompiluje i działa dobrze z GCC:

g++ -Wall -pedantic locale.cpp 
    <= No errorrs, no warnings 

./a.out 
The locale is 'en_US.UTF-8' 
    <= Expected output 

Uzupełnienie:

dokładnie to samo z MSVS 2013 - bez kompilacji błędów i ostrzeżeń; żadnych błędów uruchomiony:

locale.cpp =>

#include <iostream> 
#include <locale> 
#include <string> 

int main() { 
    std::cout << "The locale is '" << std::locale("").name() << "'" << std::endl; 
} 

wyjściowa =>

locale 
The locale is 'English_United States.1252'