ARM64 crash when using static block allocator with small types
kevin-- opened this issue · comments
Crash when deallocating shared_ptr building for arm64
-- Xcode Apple clang version 14.0.3 (clang-1403.0.22.14.1)
Has been happening for a couple major Xcode versions so far.
Example program
using StaticMemoryPoolAllocator =
foonathan::memory::memory_pool<foonathan::memory::node_pool, foonathan::memory::static_block_allocator>
size_t Capacity = 20;
using TestType = int;
using NodeSize = shared_ptr_stateful_node_size<TestType>;
constexpr size_t storage_size_bytes = StaticMemoryPoolAllocator::min_block_size( NodeSize::value, Capacity );
// setup storage & pool
foonathan::memory::static_allocator_storage<storage_size_bytes> storage;
StaticMemoryPoolAllocator pool( NodeSize::value, storage_size_bytes, storage );
// test case
std::list<std::shared_ptr<TestType>> retain;
for ( size_t i = 0; i < capacity; ++i ) {
retain.push_back( foonathan::memory::allocate_shared<TestType>( pool ) );
}
retain.clear(); // < crash here
In fact, resetting the shared_ptr of the 2nd created item can cause a crash.
In my experimenting, the only thing that alleviated the crash was to use TestType
with a sizeof
8 or higher.
I don't have access to XCode, can you please give me the following information:
shared_ptr_stateful_node_size<TestType>::value
- How many bytes are allocated by
memory::allocate_shared<TestType>(pool)
(you can find it out by setting a breakpoint instd_allocator::allocate
, the value isn * sizeof(T)
of whatever allocator instantiation was being used. - If there is a mismatch between 1 and 2, the output of
nodesize_dbg --verbose
Thank you.
Sorry for the long delay, here is the info
using TestType = int;
sizeof(int)
= 4,alignof(int)
= 4shared_ptr_stateful_node_size<int>::value
= 44memory::allocate_shared<TestType>(pool)
->std_allocator::allocate
= n = 1std::allocator::allocate_impl
:taking thevoid* allocate_impl(std::false_type, size_type n) { if (n == 1) return this->allocate_node(sizeof(T), alignof(T)); else return this->allocate_array(n, sizeof(T), alignof(T)); }
n == 1
branch here,sizeof(T)
= 40,alignof(T)
= 8.- so I think therefore it is allocating 48, but the determined size is 44 from (1) above
- see attached nodesize_dbg_verbose.txt
It seems the discrepancy in (1) is that detail::shared_ptr_stateful_node_size<alignof(T)>::value + sizeof(T)
here we take the alignof(int)
BUT in (2) the allocator impl is taking the alignof(shared_ptr_stateful_node_size<int>)
The type of the std_allocator
is
foonathan::memory::std_allocator<
std::__shared_ptr_emplace<
int,
foonathan::memory::std_allocator<
int,
rt::StaticMemoryPool<
20,
shared_ptr_stateful_node_size<int>,
rt::container_overhead::None
>
>
>,
rt::StaticMemoryPool<
20,
shared_ptr_stateful_node_size<int>,
rt::container_overhead::None
>
>
The rt::StaticMemoryPool
is my implementation of an allocator-- the 1st argument is the capacity, the 2nd template argument is used to determine the size of the nodes