简体   繁体   English

这个简单的C ++程序使用<locale>是否正确?

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

This code seemed to work ok in (ubuntu trusty) versions of gcc and clang, and in Win 7 on a VM via mingw... Recently I upgraded to Wily and builds made with clang crash consistently here. 这个代码似乎在(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;
}

Sometimes its a gibberish string followed by Aborted: Core dumped and sometimes its invalid free . 有时它是一个乱码的字符串,然后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)

(Both program outputs above were abbreviated greatly or they would not fit in this question.) (上述两个节目输出都大大缩短,或者它们不适合这个问题。)

I also got an invalid free on Coliru with it as well. 我也在Coliru上也获得了无效免费

But this is very similar to example code on cppreference : 但这与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';
}

Actually that code crashes Coliru also... :facepalm: 实际上代码崩溃了Coliru ......:facepalm:

More crashes of similar code from Coliru. 更多来自Coliru的类似代码的崩溃

Is this a bug in the c++ library used by clang, or is this code defective? 这是clang使用的c ++库中的错误,还是这个代码有缺陷?

Note also: These crashes seem to be restricted to the C++ api, if you use <clocale> instead things seem to work okay, so it may just be some trivial problem in the C++ bindings over this? 还要注意:这些崩溃似乎仅限于C ++ api,如果你使用<clocale>而不是事情似乎工作正常,那么它可能只是C ++绑定中的一些微不足道的问题呢?

Variations using setlocale : 1 2 3 使用setlocale变体: 1 2 3

Looks like this is caused by libstdc++'s ABI change in its basic_string , which was needed for C++11 conformance. 看起来这是由libstdc ++的basic_string的ABI更改引起的,这是C ++ 11一致性所需要的。 To manage this transition, GCC added the abi_tag attribute, which changes the mangled name of functions so that functions for the new and old ABI can be distinguished, even if the change wouldn't otherwise affect the mangled name (eg the return type of a function). 为了管理这种转换,GCC添加了abi_tag属性,该属性更改了函数的错位名称,以便可以区分新旧ABI的函数,即使更改不会影响错位名称(例如,返回类型功能)。

This code 这段代码

#include <locale>
#include <string>

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

on GCC emits a call to _ZNKSt6locale4nameB5cxx11Ev , which demangles to std::locale::name[abi:cxx11]() const , and returns a SSO string with the new ABI. 在GCC上发出对 _ZNKSt6locale4nameB5cxx11Ev 的调用 ,该调用 _ZNKSt6locale4nameB5cxx11Evstd::locale::name[abi:cxx11]() const ,并返回带有新ABI的SSO字符串。

Clang, on other other hand, doesn't support the abi_tag attribute , and emits a call to _ZNKSt6locale4nameEv , which demangles to simply std::locale::name() const - which is the version returning a COW string (the old ABI). 另一方面,Clang 不支持abi_tag属性 ,并发出对 _ZNKSt6locale4nameEv 的调用 ,该_ZNKSt6locale4nameEvstd::locale::name() const - 这是返回COW字符串的版本(旧的ABI) 。

The net result is that the program ends up trying to use a COW string as an SSO string when compiled with Clang. 最终结果是程序在使用Clang编译时最终尝试使用COW字符串作为SSO字符串。 Havoc ensues. 随之而来的是浩劫。

The obvious workaround is to force the old ABI via -D_GLIBCXX_USE_CXX11_ABI=0 . 显而易见的解决方法是通过-D_GLIBCXX_USE_CXX11_ABI=0强制旧ABI。

I think the "" parameter might be corrupting something. 我认为""参数可能会破坏某些东西。 I don't think it's a legal argument? 我不认为这是一个法律论点?

To verify it's nothing else, try running this: 要验证它没有别的,请尝试运行:

#include <iostream>
#include <locale>

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

It compiles and runs just fine with GCC: 它通过GCC编译并运行得很好:

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

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

ADDENDUM: 附录:

Exactly the same with MSVS 2013 - no errors or warnings compiling; 与MSVS 2013完全相同 - 没有错误或警告编译; no errors running: 没有错误运行:

locale.cpp => locale.cpp =>

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

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

Output => 输出=>

locale
The locale is 'English_United States.1252'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM