==16301== Invalid read of size 8 ==16301== at 0x843457: mem_alloc_description<pool_usage>::release_instance_overhead(void*, unsigned long, bool) (mem-stats.h:513) ==16301== by 0x8427C4: base_pool_allocator<memory_block_pool>::release() (alloc-pool.h:311) ==16301== by 0x84299D: base_pool_allocator<memory_block_pool>::~base_pool_allocator() (alloc-pool.h:335) ==16301== by 0x844E1B: object_allocator<cselib_val>::~object_allocator() (alloc-pool.h:474) ==16301== by 0x5E13058: __run_exit_handlers (in /lib64/libc-2.18.so) ==16301== by 0x5E130A4: exit (in /lib64/libc-2.18.so) ==16301== by 0x5DFCBEB: (below main) (in /lib64/libc-2.18.so) ==16301== Address 0x72529b0 is 1,088 bytes inside a block of size 3,048 free'd ==16301== at 0x4C28ADC: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) ==16301== by 0x844C81: xcallocator<hash_map<void const*, mem_usage_pair<pool_usage>, simple_hashmap_traits<default_hash_traits<void const*>, mem_usage_pair<pool_usage> > >::hash_entry>::data_free(hash_map<void const*, mem_usage_pair<pool_usage>, simple_hashmap_traits<default_hash_traits<void const*>, mem_usage_pair<pool_usage> > >::hash_entry*) (hash-table.h:273) ==16301== by 0x14DC512: hash_table<hash_map<void const*, mem_usage_pair<pool_usage>, simple_hashmap_traits<default_hash_traits<void const*>, mem_usage_pair<pool_usage> > >::hash_entry, xcallocator>::~hash_table() (hash-table.h:627) ==16301== by 0x14DCD77: hash_map<void const*, mem_usage_pair<pool_usage>, simple_hashmap_traits<default_hash_traits<void const*>, mem_usage_pair<pool_usage> > >::~hash_map() (hash-map.h:26) ==16301== by 0x14DCE52: mem_alloc_description<pool_usage>::~mem_alloc_description() (mem-stats.h:559) ==16301== by 0x5E13058: __run_exit_handlers (in /lib64/libc-2.18.so) ==16301== by 0x5E130A4: exit (in /lib64/libc-2.18.so) ==16301== by 0x5DFCBEB: (below main) (in /lib64/libc-2.18.so)
Too much C++ here I guess? ==16301== by 0x14DCE52: mem_alloc_description<pool_usage>::~mem_alloc_description() (mem-stats.h:559) vs. ==16301== by 0x8427C4: base_pool_allocator<memory_block_pool>::release() (alloc-pool.h:311) ==16301== by 0x84299D: base_pool_allocator<memory_block_pool>::~base_pool_allocator() (alloc-pool.h:335) ==16301== by 0x8E25D3: object_allocator<et_occ>::~object_allocator() (alloc-pool.h:474) where the latter calls release_instance_overhead. extern mem_alloc_description<pool_usage> pool_allocator_usage; comes from alloc-pool.c. Looks like when linking LTO we get the bad destructor order (by luck?). Leaking pool_allocator_usage will fix this (making it a reference). A very bit ugly though. Index: gcc/alloc-pool.c =================================================================== --- gcc/alloc-pool.c (revision 233633) +++ gcc/alloc-pool.c (working copy) @@ -24,7 +24,7 @@ along with GCC; see the file COPYING3. #include "alloc-pool.h" ALLOC_POOL_ID_TYPE last_id; -mem_alloc_description<pool_usage> pool_allocator_usage; +mem_alloc_description<pool_usage> &pool_allocator_usage = *(new mem_alloc_description<pool_usage>); /* Output per-alloc_pool memory usage statistics. */ void Index: gcc/alloc-pool.h =================================================================== --- gcc/alloc-pool.h (revision 233633) +++ gcc/alloc-pool.h (working copy) @@ -95,7 +95,7 @@ struct pool_usage: public mem_usage const char *m_pool_name; }; -extern mem_alloc_description<pool_usage> pool_allocator_usage; +extern mem_alloc_description<pool_usage> &pool_allocator_usage; #if 0 /* If a pool with custom block size is needed, one might use the following
Or maybe simply making mem_alloc_description::~mem_alloc_description () empty.
Created attachment 37782 [details] Suggested patch Well, the situation is not so easy. Ideally, I would set m_reverse_map = NULL in mem_alloc_description<T>::~mem_alloc_description () and guard release_object_overhead and release_instance_overhead with probes if m_* != NULL. But as the assignment in the dtor is optimized out by DSE, because it's undefined to check member of a destroyed instance. Thus I suggest a small work-around that can survive lto.exp and LTO bootstrap goes to stage3 (still running). What do you think about it?
On Wed, 24 Feb 2016, marxin at gcc dot gnu.org wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69919 > > --- Comment #3 from Martin Liška <marxin at gcc dot gnu.org> --- > Created attachment 37782 [details] > --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=37782&action=edit > Suggested patch > > Well, the situation is not so easy. Ideally, I would set m_reverse_map = NULL > in > mem_alloc_description<T>::~mem_alloc_description () and guard > release_object_overhead and release_instance_overhead with probes if m_* != > NULL. > > But as the assignment in the dtor is optimized out by DSE, because it's > undefined to check member of a destroyed instance. > > Thus I suggest a small work-around that can survive lto.exp and LTO bootstrap > goes to stage3 (still running). > > What do you think about it? I guess it'll work.
Author: marxin Date: Thu Feb 25 16:57:39 2016 New Revision: 233722 URL: https://gcc.gnu.org/viewcvs?rev=233722&root=gcc&view=rev Log: Do not gather mem stats in run_exit_handles (PR PR middle-end/69919 * alloc-pool.c (after_memory_report): New variable. * alloc-pool.h (base_pool_allocator ::release): Do not use the infrastructure if after_memory_report. * toplev.c (toplev::main): Mark after memory report. Modified: trunk/gcc/ChangeLog trunk/gcc/alloc-pool.c trunk/gcc/alloc-pool.h trunk/gcc/toplev.c
Fixed in trunk.