[ANN] --enable-dbgutil: everyone gets a Debug STL!
Stephan Bergmann
sbergman at redhat.com
Wed Apr 17 23:31:22 PDT 2013
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
More information about the LibreOffice
mailing list