> > the rest of the find()'s were spot on. This is not a proper fix though, as > > the magic number 8 has to have some reasonable explanation (which I don't have). Or > > at least the size should be detected in runtime. Thanks again. > > As noted, I have personally been trying to get an explanation of that whole safety > find mechanism for years now...
I wasn't the one to add it, but I can explain why it works.
MAME's font subsystem uses new [] to allocate an array of glyphs. glyph has non-trivial destructor, so g++ inserts an array cookie in front of the array. Internally, g++ emits code like this:
Code:
void *p1 = operator new[](size + cookie_size, ...) type *p2 = (type *)((char *)p1 + cookie_size); // set cookie at p1, then construct all elements of p2 in-place return p2;
The trick is that MAME sets up the array's memory_entry *inside* its custom allocator (i.e., for p1) but later tries to look up p2. Normally the cookie is sizeof(size_t) bytes, so on failure you can just back up sizeof(size_t) bytes and try again.
This blows up on 32-bit ARM, where sizeof(size_t) == 4 and the ARM C++ ABI specifies an 8-byte array cookie. It could also blow up on other platforms if g++ ever needs to add padding after the array cookie, but that only happens if alignof(type) > sizeof(size_t) which is pretty unlikely (and IIRC impossible on most platforms).
Technically resource_pool is relying on non-portable behavior, but fixing it the "right" way would mean rearranging a bunch of the memory allocation code so that the memory_entry gets populated after g++ fixes up the pointer. Or just do the simple workaround -- add an ARM-specific #ifdef that uses 8 instead of sizeof(size_t), and cross your fingers that g++ never needs padding on other platforms.
|