2015-12-07 12 views
9

Questo codice sembrava funzionare bene nelle versioni (ubuntu trusty) di gcc e clang, e in Win 7 su una VM tramite mingw ... Recentemente ho aggiornato a Wily e le build fatte con clang si sono verificate costantemente qui.È corretto questo semplice programma C++ utilizzando <locale>?

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

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

A volte è una stringa senza senso seguita da Aborted: Core dumped e, talvolta, la sua 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) 

(Entrambe le uscite di programma sopra sono stati abbreviato notevolmente altrimenti non si adatterebbe in questa domanda.)

Ho anche avuto un invalid free on Coliru con esso pure.

Ma questo è molto simile al codice di esempio su 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'; 
} 

In realtà quel codice crashes Coliru anche ...: facepalm:

Morecrashes di codice simile da Coliru.

Si tratta di un bug nella libreria C++ utilizzato da clang, oppure questo codice è difettoso?

Nota anche: questi incidenti sembrano essere limitato alle API C++, se si utilizza <clocale> invece le cose sembrano funzionare bene, quindi potrebbe essere solo qualche problema banale nei binding C++ oltre questo?

Variazioni utilizzando setlocale: 123

+0

Sembra ovviamente un bug per me. Hai preso in considerazione la possibilità di chiedere la mailing list clang e/o segnalarla come un bug? Sembra un posto più appropriato da chiedere ... –

+0

Se clang, il compilatore, si blocca compilando questo codice, allora questo è un bug clang e dovrebbe essere segnalato. –

+0

@LightnessRacesinOrbit: Sì, immagino che questo sia il passo successivo –

risposta

6

Sembra che questo è causato da libstdc 's ++ cambiamento ABI nella sua basic_string, che era necessario per C++ 11 conformità. Per gestire questa transizione, GCC ha aggiunto l'attributo abi_tag, che modifica il nome di funzioni alterato in modo da poter distinguere le funzioni per l'ABI nuovo e vecchio, anche se la modifica non influirebbe altrimenti sul nome mutilato (ad esempio il tipo di ritorno di un funzione).

Questo codice

#include <locale> 
#include <string> 

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

su GCC emits a call to_ZNKSt6locale4nameB5cxx11Ev, che demangles a std::locale::name[abi:cxx11]() const, e restituisce una stringa SSO con il nuovo ABI.

Clang, su altri invece, doesn't support the abi_tag attribute, e emits a call to_ZNKSt6locale4nameEv, che demangles semplicemente std::locale::name() const - che è la versione restituendo una stringa COW (il vecchio ABI).

Il risultato netto è che il programma finisce per provare a utilizzare una stringa COW come una stringa SSO quando compilata con Clang. Segue il colpo

L'ovvia soluzione è forzare il vecchio ABI tramite -D_GLIBCXX_USE_CXX11_ABI=0.

+0

wow, questo è un bel investigatore! Questo lo risolve sulla mia macchina e su coliru: http://coliru.stacked-crooked.com/a/b08f590618a7398a, http://coliru.stacked-crooked.com/a/0c769ee07e51fb02 –

1

penso che il parametro "" potrebbe essere corrompendo qualcosa. Non penso che sia un argomento legale?

Per verificare che non è niente altro, provare a eseguire questo:

#include <iostream> 
#include <locale> 

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

Questo dovrebbe essere un commento. –

1

Si compila e funziona bene con GCC:

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

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

APPENDICE:

esattamente lo stesso con MSVS 2013 - nessun errore o compilazione di avvisi; nessun errore in esecuzione:

locale.cpp =>

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

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

uscita =>

locale 
The locale is 'English_United States.1252' 
Problemi correlati