简体   繁体   中英

Why does creating 2 variables cause a crash in custom STL, C++ VS2019?

Hello I'm trying to rewrite my own memory manager and STL (nothing fancy, just some basic vector and string features) and I'm getting a strange behaviour. I'm trying to get experience in the memory management field because I'm a high school student with time to spare. The problem is, when I create my first variable everything goes perfectly but after creating the second variable, the program crashes while creating the first variable.

String.h/.cpp

    class String {
        char* pointer_toBuffer = nullptr;
        size_t buffer_length = 0;
        IAllocator* Allocator;
    public:
        String(const char* text, IAllocator* Allocator);}

    String::String(const char* text, TuranAPI::MemoryManagement::IAllocator* MemoryAllocator) : Allocator(MemoryAllocator) {
        std::cout << "String creation has started: " << text << std::endl;
        unsigned int i = 0;
        while (text[i] != 0) {
            i++;
        }
        buffer_length = i + 1;
        pointer_toBuffer = (char*)Allocator->Allocate_MemoryBlock(buffer_length * sizeof(char));//When I write the Second String part, FirstString crashes directly. I use VSDebug and it says access violation here while creating FirstString. It is successful if I delete the SecondString part.
        for (unsigned int letterindex = 0; letterindex < i; letterindex++) {
            pointer_toBuffer[letterindex] = text[letterindex];
        }
        pointer_toBuffer[i] = 0;
    }

MemoryManagement.h/cpp

    TAPIMemoryAllocator::TAPIMemoryAllocator(MemoryBlockInfo MemoryPool_toUse){
        std::cout << "TAPIMemoryAllocator is created!\n";
        std::cout << "MemoryPool's start pointer: " << MemoryPool_toUse.address << std::endl;
        MemoryPool.address = MemoryPool_toUse.address;
        MemoryPool.size = MemoryPool_toUse.size;
        SELF = this;
    }
    void* TAPIMemoryAllocator::Allocate_MemoryBlock(size_t size) {
        std::cout << "MemoryPool's start pointer: " << MemoryPool.address << std::endl;
        std::cout << "A buffer of " << size << " bytes allocation request found in TAPIMemoryAllocator!\n";
        if (SELF == nullptr) {
            TMemoryManager First(1024 * 1024 * 1024 * 1);
            MemoryBlockInfo FirstMemoryBlock;
            FirstMemoryBlock.address = SELF->MemoryPool.address;
            FirstMemoryBlock.size = size;
            Allocated_MemoryBlocks[0] = FirstMemoryBlock;
            return (char*)SELF->MemoryPool.address;
        }
        void* finaladdress = SELF->MemoryPool.address;
        for (unsigned int blockindex = 0; blockindex < MAX_MEMORYBLOCKNUMBER; blockindex++) {
            MemoryBlockInfo& MemoryBlock = Allocated_MemoryBlocks[blockindex];
            finaladdress = (char*)finaladdress + MemoryBlock.size;
            if (size <= MemoryBlock.size && MemoryBlock.address == nullptr) {
                std::cout << "Intended block's size is less than found memory block!\n";
                MemoryBlock.address = finaladdress;
                //You shouldn't change Memory Block's size because all of the allocations before this are based upon the previous size!
                //You should move all the previous allocated memory to set the size (which is not ideal!)
                //If I'd want to find memory leaks causing this, I could write code here to log the leaks!
                return MemoryBlock.address;
            }
            else if (MemoryBlock.size == 0 && MemoryBlock.address == nullptr) {
                std::cout << "An empty block is created for intended block! Block's Array index is: " << blockindex << "\n";
                std::cout << "MemoryPool's start pointer: " << MemoryPool.address << std::endl << "MemoryBlock's pointer: " << finaladdress << std::endl;
                //This means this index in the Allocated_MemoryBlocks has never been used, so we can add the data here!
                MemoryBlock.address = finaladdress;
                MemoryBlock.size = size;
                return MemoryBlock.address;
            }
        }
        //If you arrive here, that means there is no empty memory block in the Allocated_MemoryBlocks array!
        std::cout << "There is no empty memory block in the Allocated_MemoryBlocks array, so nullptr is returned!\n";
        return nullptr;
    }

    TMemoryManager::TMemoryManager(size_t Main_MemoryBlockSize) {
        if (SELF != nullptr) {
            std::cout << "You shouldn't create a MemoryManager!";
            return;
        }
        std::cout << "TMemoryManager is created!\n";
        MainMemoryBlock.address = malloc(Main_MemoryBlockSize);
        MainMemoryBlock.size = Main_MemoryBlockSize;
        SELF = this;
        std::cout << "Main Memory Block's start pointer: " << MainMemoryBlock.address << std::endl;

        MemoryBlockInfo TuranAPI_MemoryPool;
        TuranAPI_MemoryPool.address = MainMemoryBlock.address;
        std::cout << "TuranAPI_MemoryPool.address: " << TuranAPI_MemoryPool.address << std::endl;
        TuranAPI_MemoryPool.size = 1024 * 1024 * 10;
        TAPIMemoryAllocator Create(TuranAPI_MemoryPool);
    }
    TMemoryManager* TMemoryManager::SELF = nullptr;
    TMemoryManager First(1024 * 1024 * 1024 * 1);

Main.cpp

String FirstString("How are you?", TAPIMemoryAllocator::SELF);
std::cout << FirstString << std::endl; //If I delete the below, it prints "How are you?" as expected
String SecondString("I'm fine, thanks!", TAPIMemoryAllocator::SELF);
std::cout << SecondString << std::endl; 

Solved: The problem was in Allocator. When allocator goes out of scope, it's Allocate_MemoryBlock function (it's a virtual function, not static) is deleted. I don't know why it doesn't occur when only one String is created (maybe a compiler optimization) but storing Allocator's itself (All of variables was static already) and assinging SELF as stored one's pointer solved the problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM