删除对象时出现C ++自定义内存管理器错误

时间:2016-11-15 14:34:56

标签: c++ memory-management

那里。

我正在开发一个自定义虚拟机,我正在使用自定义内存管理类(每个对象将驻留在虚拟机将管理的一大块内存中)。

问题是:当尝试删除其中一个对象时,valgrind给我“跳转到下一行所述的无效地址”错误,我无法弄清楚如何修复它。

有没有人有线索?提前谢谢。

valgrind错误:

[Stub] static void CeliVM::MemoryManagedClass::operator delete(pointer) in /home/patrick/Projects/CeliVM/Source/Memory.cxx @ 507
==4812== Jump to the invalid address stated on the next line
==4812==    at 0x310040529CBA0040: ???
==4812==    by 0x401CA2: main (Main.cxx:89)
==4812==  Address 0x310040529cba0040 is not stack'd, malloc'd or (recently) free'd
==4812==

删除操作符:

void MemoryManagedClass::operator delete ( pointer objectPointer ) noexcept
{
    MemoryAllocator* memoryAllocator = static_cast<MemoryManagedClass*>( objectPointer )->memoryAllocator;
    memoryAllocator->Free( DATA( objectPointer ) );
}

内存分配器“免费”方法:

void BasicMemoryAllocator::Free( data dataBlock )
{
    // Find the allocated block on the list.

    u64 allocatedBlockIndex = Kernel.Any;

    for ( u64 blockIndex = 0; blockIndex < this->numberOfAllocatedBlocks; blockIndex++ )
        if ( this->allocatedBlocks[ blockIndex ].block == dataBlock )
        {
            allocatedBlockIndex = blockIndex;
            break;
        }

    if ( allocatedBlockIndex == Kernel.Any )
    {
        ERROR( Txt::CouldNotFindRequestedAllocatedBlock, intpointer( dataBlock ) );
        return;
    }

    // Check if we have an adjacent free block we can expand or we need to create a new one.

    u64 freeBlockIndex = Kernel.Any;

    for ( u64 blockIndex = 0; blockIndex < this->numberOfFreeBlocks; blockIndex++ )
        if ( ( this->freeBlocks[ blockIndex ].start == this->allocatedBlocks[ allocatedBlockIndex ].end + 1 ) ||
             ( this->freeBlocks[ blockIndex ].end == this->allocatedBlocks[ allocatedBlockIndex ].start - 1 ) )
        {
            freeBlockIndex = blockIndex;
            break;
        }

    if ( freeBlockIndex == Kernel.Any )
    {
        // If we do not have more "free blocks" to use, we must expand the free blocks list.

        if ( this->numberOfFreeBlocks == this->freeBlocksCapacity )
        {
            BlockInfo* newFreeBlocks = new (std::nothrow) BlockInfo[ this->freeBlocksCapacity + BasicMemoryAllocator::BlocksCapacityIncrement ];

            if ( !newFreeBlocks )
            {
                ERROR( Txt::CouldNotExpandFreeBlocksList );
                return;
            }

            memcpy( newFreeBlocks, this->freeBlocks, this->freeBlocksCapacity * sizeof( BlockInfo ) );

            delete [] this->freeBlocks;
            this->freeBlocks = newFreeBlocks;
            this->freeBlocksCapacity += BasicMemoryAllocator::BlocksCapacityIncrement;

            DEBUG( Dbg::FreeBlocksListExpanded, this->freeBlocksCapacity );
        }

        memcpy( &this->freeBlocks[ this->numberOfFreeBlocks++ ], &this->allocatedBlocks[ allocatedBlockIndex ], sizeof( BlockInfo ) );
    }
    else
        {
            // Join the freed block to the adjacent free block.

            this->freeBlocks[ freeBlockIndex ].size += this->allocatedBlocks[ allocatedBlockIndex ].size;

            if ( this->freeBlocks[ freeBlockIndex ].start == this->allocatedBlocks[ allocatedBlockIndex ].end + 1 )
                this->freeBlocks[ freeBlockIndex ].start = this->allocatedBlocks[ allocatedBlockIndex ].start;
            else
                this->freeBlocks[ freeBlockIndex ].end = this->allocatedBlocks[ allocatedBlockIndex ].end;
        }


    // Remove the allocated block from the allocated blocks list.

    u64 blockStart = this->allocatedBlocks[ allocatedBlockIndex ].start;
    u64 blockEnd = this->allocatedBlocks[ allocatedBlockIndex ].end;

    this->numberOfAllocatedBlocks--;

    if ( allocatedBlockIndex < this->numberOfAllocatedBlocks )
        memcpy( &this->allocatedBlocks[ allocatedBlockIndex ], &this->allocatedBlocks[ this->numberOfAllocatedBlocks ], sizeof( BlockInfo ) );

    DEBUG( Dbg::BlockFreed, blockStart, blockEnd );
}

1 个答案:

答案 0 :(得分:0)

编辑:

有问题的类有一个虚拟析构函数,但基类没有。将虚拟析构函数添加到基类似乎可以解决问题。

好吧,在对象之前分配一个额外的int64并保存内存分配器地址似乎解决了这个问题:当删除对象时,可以在内存中找到用于分配对象的内存分配器的地址。

<avp name="Host-IP-Address" code="257" mandatory="must" protected="may" may-encrypt="no" vendor-bit="mustnot">
    <type type-name="IPAddress"/>
</avp>

删除:

pointer MemoryManagedClass::operator new ( size_t dataSize, MemoryAllocator* memoryAllocator ) noexcept
{
    pointer objectAddress = memoryAllocator->Get( dataSize + sizeof( i64 ) );

    if ( !objectAddress )
        return NULL;

    static_cast<MemoryManagedClass*>( objectAddress )->memoryAllocator = memoryAllocator;

    i64 allocatorAddress = intpointer( memoryAllocator );
    memcpy( objectAddress, &allocatorAddress, sizeof( i64 ) );

    return DATA( objectAddress ) + sizeof( i64 );
}