This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
gcc-3.4.0: mt_allocator crashes due to alignment problems on SPARC targets when sizeof(type) <= 2
- From: Brad Spencer <spencer at infointeractive dot com>
- To: libstdc++ at gcc dot gnu dot org
- Date: Tue, 4 May 2004 19:12:10 -0300
- Subject: gcc-3.4.0: mt_allocator crashes due to alignment problems on SPARC targets when sizeof(type) <= 2
It appears that when sizeof(type) is less than or equal to 2, the
mt_allocator does not ensure proper alignment of the block_record
structures when building the freelists. This causes the allocator
code itself to crash during initialization.
On sparc-sun-solaris2.8 with gcc-3.4.0, the following small program
crashes with a bus error when TEST_SIZE <= 2.
#include <memory>
struct a { char a[TEST_SIZE]; };
int
main()
{
std::allocator<a> x;
x.allocate(1);
return 0;
}
I'm using a single-threaded build, so the offending code starts at
around line 391 of mt_allocator.h, but it appears in similar form in
two places. An excerpt from line 391:
block_count--;
block = __bin.first[0];
while (block_count > 0)
{
char* __c = reinterpret_cast<char*>(block) + bin_size;
block->next = reinterpret_cast<block_record*>(__c);
block = block->next;
block_count--;
}
block->next = NULL;
Note that __bin.first[0] comes from memory allocated with ::operator
new(), so it is properly aligned. The initialization of the first
block works as a result, but bin_size is 5 (sizeof(void *) +
sizeof(bool)), so after the first iteration, "block->next" becomes an
illegal address for multibyte access, and crashes.
I think all that has to happen is for bin_size to be rounded up to the
minimum (not necessarily the most time efficient) alignment for the
architecture. This might mean that bins with a size less than that
minimum alignment are simply not usable (i.e. not useful) on such
architectures? That is, perhaps we may as well not have a bin size
less than the minimum alignment size we'd have to pad it anyway?
I'm not familiar with the details of the new mt_allocator
implementation, but I can work up a patch attempt if necessary. Just
let me know if I should. (BTW, I found this when boost::regex crashed
in a constructor on this target.) I started out by just changing
the _S_initialize() __bin_size and __bin_max to 2 as an experiment,
but that didn't appear to be enough. :(
Also, I wasn't aware that the default allocator had become "new", at
least for Solaris targets. Was this intentional?
One more detail: Is it intentional that _S_init is never set to true
when _S_options._M_force_new is true? It's not causing problems, but
it does mean _S_initialize() is called (and then immediately
short-circuited) on every allocation, which confused me while
debugging.
--
------------------------------------------------------------------
Brad Spencer - spencer@infointeractive.com - "It's quite nice..."
Systems Architect | InfoInterActive Corp. | A Canadian AOL Company