[cfe-dev] std::use_facet<std::ctype<char>> crashes on linux

Howard Hinnant hhinnant at apple.com
Mon Aug 19 09:36:18 PDT 2013


Ok, I've seen this one before:

------------------------------------------------------------------------
r160785 | hhinnant | 2012-07-26 12:14:37 -0400 (Thu, 26 Jul 2012) | 1 line

locale::id really needs to be constructed at compile time.
------------------------------------------------------------------------
Index: include/__locale
===================================================================
--- include/__locale	(revision 160784)
+++ include/__locale	(revision 160785)
@@ -119,7 +119,7 @@
 
     static int32_t __next_id;
 public:
-    _LIBCPP_INLINE_VISIBILITY id() {}
+    _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR id() :__id_(0) {}
 private:
     void __init();
     void operator=(const id&); // = delete;

The old design was to count on the loader to zero out the id, and if the ctor happened afterwards, it did nothing.  This was replaced with an attempt to force the construction at compile time.  I don't recall exactly why the old design started failing, but it did, at about the same time constexpr was introduced into clang.

Unfortunately we can not apply constexpr to:

locale::id ctype<char>::id;

because it isn't truly const.  It gets modified the first time its __get() function gets called.

None of this is 100% portable code.  It is currently working on apple platforms.  I'm not sure why it is not working on linux.  We can #ifdef the id() ctor if need be.  Or if there is some clang-specfic syntax to force a zero-initialization at compile/link time and after that consider the class constructed, that would be fine too.  I don't know what that syntax is though.

Howard

On Aug 19, 2013, at 12:20 PM, toki loki <tokiloki7 at gmail.com> wrote:

> Problems is static constructor of
> 
> locale::id ctype<char>::id;
> 
> is called after
>     install(&make<_VSTD::ctype<char> >((ctype_base::mask*)0, false, 1u));
> 
> 
> ~"#0  id (this=<optimized out>) at /home/vv/kom/libcxx/include/__locale:131\n"
> >~"#1  __static_initialization_and_destruction_0 (__initialize_p=1, __priority=65535) at /home/vv/kom/libcxx/src/locale.cpp:879\n"
> >~"#2  0xb7f350bd in _GLOBAL__sub_I_locale.cpp(void) () at /home/vv/kom/libcxx/src/locale.cpp:6144\n"
> >~"#3  0x45a7b696 in call_init.part.0 () from /lib/ld-linux.so.2\n"
> >~"#4  0x45a7b75b in _dl_init_internal () from /lib/ld-linux.so.2\n"
> 
> >~"#5  0x45a6d18f in _dl_start_user () from /lib/ld-linux.so.2\n"
> 
> 
> I use Makefile
> 
> LIBCXX_INCLUDE = $(HOME)/kom/libcxx/include/
> LIBCXX_LIB = $(HOME)/kom/libcxx-build/lib/
> LIBCXXABI_LIB = $(HOME)/kom/libcxxabi/lib/
> 
> all:
> 	clang++ -g -O0 -fno-inline -std=c++11 -stdlib=libc++ -I$(LIBCXX_INCLUDE) main.cpp -L$(LIBCXX_LIB) -Wl,-rpath $(LIBCXX_LIB) -L$(LIBCXXABI_LIB) -Wl,-rpath $(LIBCXXABI_LIB) -lc++abi -pthread
> 
> 
> and clang version clang version 3.3
> 
> 
> On Mon, Aug 19, 2013 at 6:32 PM, Howard Hinnant <hhinnant at apple.com> wrote:
> On Aug 19, 2013, at 11:10 AM, toki loki <tokiloki7 at gmail.com> wrote:
> 
> > Hi,
> >
> > Program
> >
> > #include <locale>
> > int main(int argc, char* argv[]) {
> >     std::locale loc;
> >     std::use_facet<std::ctype<char>>(loc);
> >     return EXIT_SUCCESS;
> > }
> >
> > Crashes with latest libc++ and libc++abi on Linux with backtrace
> >
> >
> > (gdb) bt
> > #0  0xb7fff424 in __kernel_vsyscall ()
> > #1  0x45abdbaf in raise () from /lib/libc.so.6
> > #2  0x45abf503 in abort () from /lib/libc.so.6
> > #3  0xb7fbf43c in abort_message (format=0xb7ff8264 "terminating with %s exception of type %s: %s") at ../src/abort_message.cpp:47
> > #4  0xb7fbf5f9 in default_terminate_handler () at ../src/cxa_default_handlers.cpp:63
> > #5  0xb7ff4f04 in std::__terminate (func=0xb7fbf4e0 <default_terminate_handler()>) at ../src/cxa_handlers.cpp:67
> > #6  0xb7ff44e5 in failed_throw (exception_header=<optimized out>) at ../src/cxa_exception.cpp:147
> > #7  __cxa_throw (thrown_object=0x804b058, tinfo=0xb7ffce50 <typeinfo for std::bad_cast>, dest=0xb7ff8170 <std::bad_cast::~bad_cast()>) at ../src/cxa_exception.cpp:242
> > #8  0xb7f14b82 in std::__1::locale::__imp::use_facet (
> >     this=0xb7fb91a0 <std::__1::locale::__imp& std::__1::(anonymous namespace)::make<std::__1::locale::__imp, unsigned int>(unsigned int)::buf>, id=28)
> >     at /home/vv/kom/libcxx/src/locale.cpp:432
> > #9  0xb7f15486 in std::__1::locale::use_facet (this=0xbfffeca0, x=...) at /home/vv/kom/libcxx/src/locale.cpp:574
> > #10 0x0804878e in main (argc=1, argv=0xbfffed54) at main.cpp:4
> >
> >
> > I have found that 'std::ctype<char>::id.__get()' is 28 for me. I have constexpr enabled.
> >
> > Thanks.
> >
> 
> The only way I know to debug this is to monitor locale::id::__init() in locale.cpp.  One needs to find out who is calling it, how often, from where, and what the current value of __next_id is, and what __id_ gets set to.  I do not have a linux box to debug this with.
> 
> The design is that this gets called exactly 28 times with a default constructed locale and that id.__get() returns __id_-1:
> 
> long
> locale::id::__get()
> {
>     call_once(__flag_, __fake_bind(&locale::id::__init, this));
>     return __id_ - 1;
> }
> 
> Furthermore locale::id::__init() is a private function of locale::id and is supposed to be only called within locale::id::__get().
> 
> One theory is:  call_once isn't working.
> 
> Howard
> 
> 




More information about the cfe-dev mailing list