Date: prev next · Thread: first prev next last
2013 Archives by date, by thread · List index


On 04/17/2013 08:43 AM, Stephan Bergmann wrote:
On 04/15/2013 03:34 PM, Michael Stahl wrote:
with commit f14f7a2e4568e3e85a0c8860beebd0376c5a8b51 MSVC builds will
link everything against the debug runtimes (MSVCRTD etc.), which enables
debug STL and other things.
[...]
since we have this enabled on other GCC platforms for years i'm not much
concerned about breakage on MacOSX; it would be helpful though if
somebody could try what happens when you run the "subsequentcheck" tests
which apparently isn't possible over SSH.

Another fallout is that, at least in
my Mac OS X 10.7.5, Xcode 4.6.1, --enable-dbgutil --with-macosx-sdk=10.7
master builds, writing numbers to std streams now suppresses all output
to those streams, so that e.g., SAL_WARN("foo","bar") only writes
"warn:foo:" to stderr (not even followed by a newline) and stops as soon
as it would write the numeric pid.

This is caused by basic_ostream::_M_insert
(/usr/include/c++/4.2.1/bits/ostream.tcc) catching an exception from
__check_facet(this->_M_num_put) and setting ios_base::badbit, which in
turn results from this->_M_num_put unexpectedly being null.  Similar
problems on (non-debug) Linux had been addressed with long ago with
consistently exporting _ZGVNSt7num_put* and _ZNSt7num_put* symbols from
all libraries.

Why _GLIBCXX_DEBUG causes this problem on Mac OS X now, and how to solve
it, is still unclear to me.

For the record, here is what happens: At least on Mac OS X 10.7.5 with Xcode 4.6.2 (with Command Line Tools installed), building the C++ program test.cc

#include <iostream>
#include <sstream>
int main() {
  std::ostringstream s;
  s << "a" << 1 << "b\n";
  std::cout << s.str();
}

with

c++ -D_GLIBCXX_DEBUG test.cc

and running it (./a.out) prints only

a

(not followed by a newline) to stdout, not

a1b

(followed by a newline).

The reason is that in basic_ostream::_M_insert (/usr/include/c++/4.2.1/bits/ostream.tcc) the __check_facet(this->_M_num_put) call throws an exception, leading to this->_M_setstate(ios_base::badbit).

This is because _M_num_put is null, because in basic_ios::_M_cache_locale (/usr/include/c++/4.2.1/bits/basic_ios.tcc) the call to has_facet<__num_put_type>(__loc) returns false.

This is because in has_facet (/usr/include/c++/4.2.1/bits/locale_facets.tcc), the call to _Facet::id._M_id() (with _Facet being __num_put_type aka num_put<_CharT,ostreambuf_iterator<_CharT,_Traits>>, see /usr/include/c++/4.2.1/bits/basic_ios.h) returns a fresh __i >= __loc._M_impl->_M_facets_size.

This is because the static

template <typename _CharT, typename _OutIter>
  locale::id num_put<_CharT, _OutIter>::id;

(/usr/include/c++/4.2.1/bits/locale_facets.h) is emitted into test.s as

  .section __DATA,__datacoal_nt,coalesced
  .globl __ZNSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE2idE ## 
@_ZNSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE2idE
  .weak_definition __ZNSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE2idE
  .align 3
__ZNSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE2idE:
  .space 8

so that a.out binds to this instance while libstdc++.6.dylib previously has used a binding to its own instance (in calls via std::ios_base::Init::Init -> ... -> std::has_facet<std::num_put<char,std::ostreambuf_iterator<char,std::char_traits<char>>>>, as can be observed in gdb).

Interestingly, while a.out contains its own weak definition of __ZNSt7num_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE2idE, it has __ZNSt5ctypeIcE2idE -- i.e.,

template<typename _CharT>
  locale::id ctype<_CharT>::id;

(/usr/include/c++/4.2.1/bits/locale_facets.h) as an undefined reference (so binds to the definition in libstdc++.6.dylib). Both are eventually needed from _M_cache_locale; the two mainly differ in the number of template parameters.

This all becomes irrelevant when compiling without -D_GLIBCXX_DEBUG, as then (/usr/include/c++/4.2.1/bits/c++config.h) _GLIBCXX_NAMESPACE_ASSOCIATION_DEBUG is 0 so that _GLIBCXX_EXTERN_TEMPLATE is 1, so that

extern template class basic_ostringstream<char>;

(/usr/include/c++/4.2.1/bits/sstream.tcc) becomes visible and the call to std::basic_ostringstream<char,std::char_traits<char>,std::allocator<char>>::basic_ostringstream(std::_Ios_Openmode) (aka __ZNSt19basic_ostringstreamIcSt11char_traitsIcESaIcEEC1ESt13_Ios_Openmode) in a.out calls directly into libstdc++.6.dylib, instead of carrying weak definitions of all the code involved above in a.out.

(It makes no difference whether to build with c++, clang++, or g++. It also makes no difference whether to also specify -D_GLIBCXX_FULLY_DYNAMIC_STRING, which is known to be required in other circumstances like <http://lists.apple.com/archives/cocoa-dev/2009/Sep/msg01199.html> "Re: getline 'free' problem." Also, results are the same at least with Xcode 4.6.1 and Xcode 4.6.2.)

Stephan

Context


Privacy Policy | Impressum (Legal Info) | Copyright information: Unless otherwise specified, all text and images on this website are licensed under the Creative Commons Attribution-Share Alike 3.0 License. This does not include the source code of LibreOffice, which is licensed under the Mozilla Public License (MPLv2). "LibreOffice" and "The Document Foundation" are registered trademarks of their corresponding registered owners or are in actual use as trademarks in one or more countries. Their respective logos and icons are also subject to international copyright laws. Use thereof is explained in our trademark policy.