This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug libstdc++/68200] New: g++ 5.2 optimizes out pointer assignment in libstdc++ mt_allocator freelist destructor, causing crash at global-dtor time


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68200

            Bug ID: 68200
           Summary: g++ 5.2 optimizes out pointer assignment in libstdc++
                    mt_allocator freelist destructor, causing crash at
                    global-dtor time
           Product: gcc
           Version: 5.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: oremanj at mit dot edu
  Target Milestone: ---

PR 52064 (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52604) added a guard
assignment to libstdc++-v3/src/c++98/mt_allocator.cc (_M_thread_freelist = 0),
so that attempts to use the freelist after it had been destroyed would not
access invalid memory. This resolved issues with global-scope STL containers
that used mt_allocator being destroyed after the mt_allocator freelist was
destroyed.

    ~__freelist()
    {
      if (_M_thread_freelist_array)
        {
          __gthread_key_delete(_M_key);
          ::operator delete(static_cast<void*>(_M_thread_freelist_array));
          _M_thread_freelist = 0;
        }
    }

The setting of the _M_thread_freelist member can validly be optimized away,
because accessing the object after its destructor has run is undefined
behavior, and the _M_thread_freelist assignment can't be detected other than by
doing that. Since PR 52064 was resolved in 2012, it appears that gcc has become
smarter about optimizing this case, and the guard assignment no longer is
compiled. I get this assembly:

0x7ffff055d4f0 <(anonymous namespace)::__freelist::~__freelist()>:
+ 0:  cmpq   $0x0,0x8(%rdi)
+ 5:  je     0x7ffff055d510 <(anonymous
namespace)::__freelist::~__freelist()+32>
+ 7:  push   %rbx
+ 8:  mov    %rdi,%rbx
+11:  mov    0x18(%rdi),%edi
+14:  callq  0x7ffff054d670 <pthread_key_delete@plt>
+19:  mov    0x8(%rbx),%rdi
+23:  pop    %rbx
+24:  jmpq   0x7ffff054b9f0 <_ZdlPv@plt>
+29:  nopl   (%rax)
+32:  repz retq 

It does seem like the existing code is taking advantage of undefined behavior,
so maybe a larger change is in order, but changing the assignment to happen
through a volatile pointer - const_cast<_Thread_record *volatile
&>(_M_thread_freelist) = 0 - resolves the issue.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]