簡體   English   中英

這個簡單的C ++程序使用<locale>是否正確?

[英]Is this simple C++ program using <locale> correct?

這個代碼似乎在(ubuntu可信賴)版本的gcc和clang中運行正常,並且在Win 7中通過mingw運行...最近我升級到Wily並且使用clang崩潰在這里進行構建。

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

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

有時它是一個亂碼的字符串,然后Aborted: Core dumped ,有時它的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)

(上述兩個節目輸出都大大縮短,或者它們不適合這個問題。)

我也在Coliru上也獲得了無效免費

但這與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';
}

實際上代碼崩潰了Coliru ......:facepalm:

更多來自Coliru的類似代碼的崩潰

這是clang使用的c ++庫中的錯誤,還是這個代碼有缺陷?

還要注意:這些崩潰似乎僅限於C ++ api,如果你使用<clocale>而不是事情似乎工作正常,那么它可能只是C ++綁定中的一些微不足道的問題呢?

使用setlocale變體: 1 2 3

看起來這是由libstdc ++的basic_string的ABI更改引起的,這是C ++ 11一致性所需要的。 為了管理這種轉換,GCC添加了abi_tag屬性,該屬性更改了函數的錯位名稱,以便可以區分新舊ABI的函數,即使更改不會影響錯位名稱(例如,返回類型功能)。

這段代碼

#include <locale>
#include <string>

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

在GCC上發出對 _ZNKSt6locale4nameB5cxx11Ev 的調用 ,該調用 _ZNKSt6locale4nameB5cxx11Evstd::locale::name[abi:cxx11]() const ,並返回帶有新ABI的SSO字符串。

另一方面,Clang 不支持abi_tag屬性 ,並發出對 _ZNKSt6locale4nameEv 的調用 ,該_ZNKSt6locale4nameEvstd::locale::name() const - 這是返回COW字符串的版本(舊的ABI) 。

最終結果是程序在使用Clang編譯時最終嘗試使用COW字符串作為SSO字符串。 隨之而來的是浩劫。

顯而易見的解決方法是通過-D_GLIBCXX_USE_CXX11_ABI=0強制舊ABI。

我認為""參數可能會破壞某些東西。 我不認為這是一個法律論點?

要驗證它沒有別的,請嘗試運行:

#include <iostream>
#include <locale>

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

它通過GCC編譯並運行得很好:

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

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

附錄:

與MSVS 2013完全相同 - 沒有錯誤或警告編譯; 沒有錯誤運行:

locale.cpp =>

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

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

輸出=>

locale
The locale is 'English_United States.1252'

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM