https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68446
--- Comment #3 from David Malcolm <dmalcolm at gcc dot gnu.org> ---
(In reply to Martin Liška from comment #2)
> Hi David.
>
> I've just verified that the invalid free is presented since introduction of
> driver::finalize in r227188.
>
> This is valgrind report coming from r230263 (one revision before the
> suspected):
[...snip...]
FWIW I'm not seeing that invalid free with trunk.
After a lot of stepping through trunk in gdb, the root cause is that:
obstack_free (obstack, NULL);
leaves an obstack in an uninitialized state and hence a reinitialization is
required, but is missing. libiberty/obstacks.texi has:
Note that if @var{object} is a null pointer, the result is an
*uninitialized* obstack. [my emphasis]
To free all memory in an obstack but leave it
valid for further allocation, call @code{obstack_free} with the address
of the first object allocated on the obstack:
@smallexample
obstack_free (obstack_ptr, first_object_allocated_ptr);
@end smallexample
In particular, obstack_free (ob, NULL) doesn't unset chunk. What was happening
is that after any call to:
obstack_free (opts_obstack, NULL);
e.g. the one in toplev::finalize, all of the chunks used by opts_obstack are
returned to memory_block_pool's m_blocks linked-list of 64KB free chunks, and
they get reused by other obstacks e.g. for bitmaps. However, given that
opts_obstack never gets reinitialized, opts_obstack.chunks points at a freed
chunk. On the 2nd iteration of a jit testcase, it gets used to allocate copies
of the options, but this out of a chunk that's being used by a different
memory_block_pool user, so chaos ensues: we have 64KB chunks of memory being
erroneously shared between different memory-pool users.
If I remove the logic to lazily initialize opts_obstacks, and instead have it
initialize it each time, then all jit test cases successfully run to completion
(5 iterations):
# of expected passes 6392
# of unexpected failures 1
FAIL: jit.dg/test-threads.c, initial compilation
with the exception of an unrelated issue building test-threads.c.exe.
I'm working on a patch for this (including poisoning memory block pool chunks
when returned to the linked list, and poisoning obstacks when freed with NULL).
Martin: can you tell me any more context on why r230264 was necessary?
Discussion seems to be here:
https://gcc.gnu.org/ml/gcc-patches/2015-11/msg01471.html