Fix a bug in Pool::Deallocate
Reviewers: mferencevic, ipaljak Reviewed By: mferencevic Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D2325
This commit is contained in:
parent
bb832de608
commit
1fa9d7752c
@ -220,10 +220,15 @@ void Pool::Deallocate(void *p) {
|
||||
ptr < reinterpret_cast<uintptr_t>(chunk.data + data_size);
|
||||
};
|
||||
auto deallocate_block_from_chunk = [this, p](Chunk *chunk) {
|
||||
// NOTE: This check is not enough to cover all double-free issues.
|
||||
CHECK(chunk->blocks_available < blocks_per_chunk_)
|
||||
<< "Deallocating more blocks than a chunk can contain, possibly a "
|
||||
"double-free situation or we have a bug in the allocator.";
|
||||
// Link the block into the free-list
|
||||
auto *block = reinterpret_cast<unsigned char *>(p);
|
||||
*block = chunk->first_available_block_ix;
|
||||
chunk->first_available_block_ix = (block - chunk->data) / block_size_;
|
||||
chunk->blocks_available++;
|
||||
};
|
||||
if (is_in_chunk(*last_dealloc_chunk_)) {
|
||||
deallocate_block_from_chunk(last_dealloc_chunk_);
|
||||
|
@ -303,6 +303,29 @@ TEST(PoolResource, AllocationWithOverflow) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(PoolResource, BlockDeallocation) {
|
||||
TestMemory test_mem;
|
||||
const size_t max_blocks_per_chunk = 2U;
|
||||
const size_t max_block_size = 64U;
|
||||
utils::PoolResource mem(max_blocks_per_chunk, max_block_size, &test_mem);
|
||||
auto *ptr = CheckAllocation(&mem, max_block_size);
|
||||
test_mem.new_count_ = 0U;
|
||||
// Do another allocation before deallocating `ptr`, so that we are sure that
|
||||
// the chunk of 2 blocks is still alive and therefore `ptr` may be reused when
|
||||
// it's deallocated. If we deallocate now, the implementation may choose to
|
||||
// free the whole chunk, and we do not want that for the purposes of this
|
||||
// test.
|
||||
CheckAllocation(&mem, max_block_size);
|
||||
EXPECT_EQ(test_mem.new_count_, 0U);
|
||||
EXPECT_EQ(test_mem.delete_count_, 0U);
|
||||
mem.Deallocate(ptr, max_block_size);
|
||||
EXPECT_EQ(test_mem.delete_count_, 0U);
|
||||
// CheckAllocation(&mem, max_block_size) will fail as PoolResource should
|
||||
// reuse free blocks.
|
||||
EXPECT_EQ(ptr, mem.Allocate(max_block_size));
|
||||
EXPECT_EQ(test_mem.new_count_, 0U);
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
||||
class ContainerWithAllocatorLast final {
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user