c++ - Difference in stringstream behavior for void* type using libc++ and libstdc++ -
the following test program returns different results depending on whether i'm using libc++ or libstdc++.
#include <sstream> #include <iostream> int main() { int = 0; void* optr = &a; void* iptr; std::stringstream ss; ss << optr; std::cout << ss.str() << '\n'; ss >> iptr; std::cout << iptr << '\n'; return 0; }
i'm using following version of clang xcode 5 on osx 10.9.2
$ xcrun clang++ --version apple llvm version 5.0 (clang-500.2.79) (based on llvm 3.3svn) target: x86_64-apple-darwin13.1.0 thread model: posix
here's output of test when built libstdc++ , libc++
$ xcrun clang++ test.cpp <-- libstdc++ version $ ./a.out 0x7fff5ec723e8 0x7fff5ec723e8 $ xcrun clang++ test.cpp -stdlib=libc++ <-- libc++ version $ ./a.out 0x7fff5205125c 0x7fff5
is bug in libc++ implementation of stringstream? usage of void* stringstream valid c++?
thanks!
yes! it's bug in libc++, in implementation of __sscanf_l
(some scanf
lookalike should take locales consideration). libstdc++ implemementation simpler.
// libc++ template <class _chart, class _inputiterator> _inputiterator num_get<_chart, _inputiterator>::do_get(iter_type __b, iter_type __e, ios_base& __iob, ios_base::iostate& __err, void*& __v) const { // stage 1 int __base = 16; // stage 2 char_type __atoms[26]; char_type __thousands_sep = 0; string __grouping; use_facet<ctype<_chart> >(__iob.getloc()).widen(__num_get_base::__src, __num_get_base::__src + 26, __atoms); string __buf; __buf.resize(__buf.capacity()); char* __a = &__buf[0]; char* __a_end = __a; unsigned __g[__num_get_base::__num_get_buf_sz]; unsigned* __g_end = __g; unsigned __dc = 0; (; __b != __e; ++__b) { if (__a_end == __a + __buf.size()) { size_t __tmp = __buf.size(); __buf.resize(2*__buf.size()); __buf.resize(__buf.capacity()); __a = &__buf[0]; __a_end = __a + __tmp; } if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc, __thousands_sep, __grouping, __g, __g_end, __atoms)) break; } // stage 3 __a[sizeof(__a)-1] = 0; #ifdef _libcpp_locale__l_extensions if (sscanf_l(__a, _libcpp_get_c_locale, "%p", &__v) != 1) #else if (__sscanf_l(__a, __cloc(), "%p", &__v) != 1) #endif __err = ios_base::failbit; // eof checked if (__b == __e) __err |= ios_base::eofbit; return __b; }
versus
// libstdc++ template<typename _chart, typename _initer> _initer num_get<_chart, _initer>:: do_get(iter_type __beg, iter_type __end, ios_base& __io, ios_base::iostate& __err, void*& __v) const { // prepare hex formatted input. typedef ios_base::fmtflags fmtflags; const fmtflags __fmt = __io.flags(); __io.flags((__fmt & ~ios_base::basefield) | ios_base::hex); typedef __gnu_cxx::__conditional_type<(sizeof(void*) <= sizeof(unsigned long)), unsigned long, unsigned long long>::__type _uintptrtype; _uintptrtype __ul; __beg = _m_extract_int(__beg, __end, __io, __err, __ul); // reset hex formatted input. __io.flags(__fmt); __v = reinterpret_cast<void*>(__ul); return __beg; }
Comments
Post a Comment