对于我最近获得的 C++ 类(class)来说,这是一个相当奇怪的作业。这个想法是使用双向链表在 C++ 中实现一个简单的内存分配器。我的 C++ 仅限于解决 Codeforces 上的问题,所以我不知道为什么似乎什么都没有打印出来。这是代码:
main.cpp
#include <iostream>
#include "tests.h"
int main() {
Tests tests = Tests();
tests.run();
return 0;
}
分配器.cpp
#include <iostream>
#include "allocator.h"
void* CleverPtr::get() const {
return data;
}
Allocator::Allocator() {
Allocator(100);//100 Bite
}
Allocator::Allocator(size_t size) {
memory = (char*)malloc(size);
head->next = nullptr;
head->prev = nullptr;
head->size = size;
head->block = memory;
head->state = FREE;
}
CleverPtr Allocator::alloc(size_t size) {
dl_l *ptr = head;
bool find = false;
while (ptr){
if (ptr->state == FREE and ptr->size >= size) {
find = true;
break;
}
ptr = ptr->next;
}
if (find) {
dl_l new_block;
new_block.next = nullptr;
new_block.prev = nullptr;
new_block.block = ptr->block;
new_block.size = size;
new_block.state = OCCUPIED;
ptr->block = (char*)((uintptr_t)(ptr->block) + size);
add_to_list(ptr->prev, &new_block, ptr);
return CleverPtr(new_block.block);
}
return CleverPtr(nullptr);
}
void Allocator::free(CleverPtr &ptr) {
dl_l * node = (dl_l*)((char *)ptr.get() - offsetof(dl_l, block));
node->state = FREE;
}
void Allocator::defrag() {
dl_l *ptr = head;
while(ptr) {
if (ptr->next) {
if (ptr->state == FREE and ptr->next->state == FREE) {
ptr->size += ptr->next->size;
remove_from_list(ptr->next);
}
}
ptr = ptr->next;
}
}
std::list<dl_l*> Allocator::show_busy_blocks() const {
dl_l *ptr = head;
std::list<dl_l*> busy_blocks = std::list<dl_l*>();
while(ptr) {
if (ptr->state == OCCUPIED) {
busy_blocks.push_back(ptr);
}
ptr = ptr->next;
}
return busy_blocks;
}
std::list<dl_l*> Allocator::show_free_blocks() const {
dl_l *ptr = head;
std::list<dl_l*> free_blocks = std::list<dl_l*>();
while(ptr) {
if (ptr->state == FREE) {
free_blocks.push_back(ptr);
}
ptr = ptr->next;
}
return free_blocks;
}
测试.cpp
#include <cassert>
#include "tests.h"
void Tests::run() {
Allocator allocator = Allocator(100);
//CleverPtr ptr = allocator.alloc(10);
//std::list<dl_l*> busy_blocks = allocator.show_busy_blocks();
//assert(busy_blocks.size()==1);
cout << "Test 1" << endl;
//CleverPtr ptr1 = allocator.alloc(10);
// std::list<dl_l*> busy_blocks1 = allocator.show_busy_blocks();
//assert(busy_blocks1.size()==2);
cout << "Test 2" << endl;
// CleverPtr ptr2 = allocator.alloc(10);
// std::list<dl_l*> busy_blocks2 = allocator.show_busy_blocks();
//assert(busy_blocks2.size()==3);
cout << "Test 3" << endl;
// allocator.free(ptr1);
//std::list<dl_l*> free_blocks = allocator.show_free_blocks();
//assert(free_blocks.size()==2);
cout << "Test 4" << endl;
//allocator.free(ptr2);
//std::list<dl_l*> free_blocks1 = allocator.show_free_blocks();
// assert(free_blocks1.size()==3);
cout << "Test 5" << endl;
//allocator.defrag();
//std::list<dl_l*> free_blocks2 = allocator.show_free_blocks();
//assert(free_blocks1.size()==1);
cout << "Test 6" << endl;
cout << "Tests done successfully" << endl;
}
分配器.h
#include <algorithm>
#include <iostream>
#include <list>
#include <cstdio>
#include "dl_list.h"
#ifndef ALLOCATORLT_ALLOCATOR_H
#define ALLOCATORLT_ALLOCATOR_H
typedef struct{
int* offset;
int size;
} block;
using namespace std;
class CleverPtr {
void* data;
public:
void* get() const;
explicit CleverPtr(void* data): data(data){}
};
class Allocator {
private:
char* memory;
dl_l* head;
public:
Allocator();
explicit Allocator(size_t size);
std::list<dl_l*> show_busy_blocks() const;
std::list<dl_l*> show_free_blocks() const;
CleverPtr alloc(size_t size);
void free(CleverPtr&);
void defrag();
};
#endif //ALLOCATORLT_ALLOCATOR_H
dl_list.h
#include <cstdint>
#ifndef ALLOCATORLT_LIST_H
#define ALLOCATORLT_LIST_H
#endif //ALLOCATORLT_LIST_H
enum STATES {FREE, OCCUPIED};
typedef struct dl_list {
struct dl_list *next;
struct dl_list *prev;
int size;
char * block;
int state;
} dl_l;
static void add_to_list(dl_l *prev_node, dl_l *new_node, dl_l *next_node) {
if (prev_node) {
prev_node->next = new_node;
new_node->prev = prev_node;
}
if (next_node) {
next_node->prev = new_node;
new_node->next = next_node;
}
}
static void remove_from_list(dl_l *node) {
if (node->prev)
node->prev->next = node->next;
if (node->next)
node->next->prev = node->prev;
}
测试.h
#include "allocator.h"
#ifndef ALLOCATORLT_TESTS_H
#define ALLOCATORLT_TESTS_H
class Tests {
public:
void run();
};
#endif //ALLOCATORLT_TESTS_H
我必须插入所有代码才能重现问题。如您所见,我注释掉了 tests.cpp
中的所有代码行,因为它们对输出没有任何影响。
Allocator allocator = Allocator(100);
行之后的所有 cout
都将被忽略,这意味着该构造函数调用有问题。不过,我不知道到底是什么。
有人可以帮我解决这个问题吗?
附言如果您碰巧注意到任何其他错误或严重错误(我怀疑有一些),请告诉我。谢谢
最佳答案
您永远不会为 head
赋值,但您可以在构造函数中使用 head->next = nullptr;
取消引用它。 head 很可能是 NULL
或指向垃圾,当您尝试访问 next
指针时会导致错误。
看这段代码:
Allocator::Allocator(size_t size) {
memory = (char*)malloc(size);
head->next = nullptr;
head->prev = nullptr;
head->size = size;
head->block = memory;
head->state = FREE;
}
您还没有将 head
设置为指向任何东西。你认为 head->next
在这里是什么?
我怀疑你的意思是:
Allocator::Allocator(size_t size) {
head = NULL;
}
没有理由在这里分配 block ,因为没有任何东西需要指向 block 的指针。
关于c++ - 为什么实例化后什么也没有发生? (C++ 内存分配器实现),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59072665/