re PR libstdc++/80721 (Sorting/Merging of free EH-emergency buffer may wrong or uncomplete)

2017-06-02  Richard Biener  <rguenther@suse.de>
	Markus Eisenmann  <meisenmann.lba@fh-salzburg.ac.at>

	PR libstdc++/80721
	* libsupc++/eh_alloc.cc (pool::free): Keep list properly
	sorted and add missing freelist item merging cases.

Co-Authored-By: Markus Eisenmann <meisenmann.lba@fh-salzburg.ac.at>

From-SVN: r248816
This commit is contained in:
Richard Biener 2017-06-02 08:10:48 +00:00 committed by Richard Biener
parent 74b4885d94
commit 1c26adb74d
2 changed files with 24 additions and 5 deletions

View File

@ -1,3 +1,10 @@
2017-06-02 Richard Biener <rguenther@suse.de>
Markus Eisenmann <meisenmann.lba@fh-salzburg.ac.at>
PR libstdc++/80721
* libsupc++/eh_alloc.cc (pool::free): Keep list properly
sorted and add missing freelist item merging cases.
2017-06-01 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
(GLIBCXX_CROSSCONFIG): Handle *-solaris* like *-linux* etc.

View File

@ -162,7 +162,7 @@ namespace
allocated_entry *x;
if ((*e)->size - size >= sizeof (free_entry))
{
// Slit block if it is too large.
// Split block if it is too large.
free_entry *f = reinterpret_cast <free_entry *>
(reinterpret_cast <char *> (*e) + size);
std::size_t sz = (*e)->size;
@ -194,13 +194,17 @@ namespace
allocated_entry *e = reinterpret_cast <allocated_entry *>
(reinterpret_cast <char *> (data) - offsetof (allocated_entry, data));
std::size_t sz = e->size;
if (!first_free_entry)
if (!first_free_entry
|| (reinterpret_cast <char *> (e) + sz
< reinterpret_cast <char *> (first_free_entry)))
{
// If the free list is empty just put the entry there.
// If the free list is empty or the entry is before the
// first element and cannot be merged with it add it as
// the first free entry.
free_entry *f = reinterpret_cast <free_entry *> (e);
new (f) free_entry;
f->size = sz;
f->next = NULL;
f->next = first_free_entry;
first_free_entry = f;
}
else if (reinterpret_cast <char *> (e) + sz
@ -224,9 +228,17 @@ namespace
> reinterpret_cast <char *> (e) + sz);
fe = &(*fe)->next)
;
// If we can merge the next block into us do so and continue
// with the cases below.
if (reinterpret_cast <char *> (e) + sz
== reinterpret_cast <char *> ((*fe)->next))
{
sz += (*fe)->next->size;
(*fe)->next = (*fe)->next->next;
}
if (reinterpret_cast <char *> (*fe) + (*fe)->size
== reinterpret_cast <char *> (e))
/* Merge with the freelist entry. */
// Merge with the freelist entry.
(*fe)->size += sz;
else
{