[Bug 251674] libc++: std::wcout does not use global locale set via setlocale()

bugzilla-noreply at freebsd.org bugzilla-noreply at freebsd.org
Tue Dec 8 19:18:40 UTC 2020


https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=251674

--- Comment #11 from Dimitry Andric <dim at FreeBSD.org> ---
(In reply to Yuri Pankov from comment #9)
> So libstdc++'s wcout being affected by setlocale() call is just an
> implementation choice, the one that libc++ didn't make?

Apparently, although that documentation link from libstdc++ that I pasted
doesn't really tell anything about it, except maybe the part:

> Locale initialization: at what point does _S_classic, _S_global get
> initialized? Can named locales assume this initialization has already taken
> place? 

but it seems this doc article is very old. Looking at libstdc++'s
implementation, it appears they initialize a default locale() object here:
https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=libstdc%2B%2B-v3/src/c%2B%2B98/ios_locale.cc#l44

  // Called only by basic_ios<>::init.
  void
  ios_base::_M_init() throw()
  {
    // NB: May be called more than once
    _M_precision = 6;
    _M_width = 0;
    _M_flags = skipws | dec;
    _M_ios_locale = locale();
  }

This default locale() object is constructed in
https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=libstdc%2B%2B-v3/src/c%2B%2B98/locale_init.cc,
but it seems like a separate copy of a C-like locale by default, e.g it has:

  void
  locale::_S_initialize_once() throw()
  {
    // 2 references.
    // One reference for _S_classic, one for _S_global
    _S_classic = new (&c_locale_impl) _Impl(2);
    _S_global = _S_classic;
    new (&c_locale) locale(_S_classic);
  }

and the _Impl constructor is:

  // Construct "C" _Impl.
  locale::_Impl::
  _Impl(size_t __refs) throw()
  : _M_refcount(__refs), _M_facets(0), _M_facets_size(num_facets),
  _M_caches(0), _M_names(0)
  {
    _M_facets = new (&facet_vec) const facet*[_M_facets_size]();
    _M_caches = new (&cache_vec) const facet*[_M_facets_size]();

    // Name the categories.
    _M_names = new (&name_vec) char*[_S_categories_size]();
    _M_names[0] = new (&name_c[0]) char[2];
    std::memcpy(_M_names[0], locale::facet::_S_get_c_name(), 2);

    // This is needed as presently the C++ version of "C" locales
    // != data in the underlying locale model for __timepunct,
    // numpunct, and moneypunct. Also, the "C" locales must be
    // constructed in a way such that they are pre-allocated.
    // NB: Set locale::facets(ref) count to one so that each individual
    // facet is not destroyed when the locale (and thus locale::_Impl) is
    // destroyed.
    _M_init_facet(new (&ctype_c) std::ctype<char>(0, false, 1));
    _M_init_facet(new (&codecvt_c) codecvt<char, char, mbstate_t>(1));
... much more of this ...
  }

So I think what you're seeing with libstdc++ is intentional, in the sense that
they have a default locale which is sort-of the same as the default C locale
(or even C.UTF-8).

The only call to setlocale() in that .cc file is when you call
std::locale::global(), as indicated in the docs.

-- 
You are receiving this mail because:
You are the assignee for the bug.


More information about the freebsd-bugs mailing list