【发布时间】:2019-11-27 14:41:37
【问题描述】:
对于我最近上的一门 C++ 课程来说,这是一个相当奇怪的作业。这个想法是使用双向链表在 C++ 中实现一个简单的内存分配器。我的 C++ 仅限于解决 Codeforces 上的问题,所以我不知道为什么似乎什么都没有打印出来。代码如下:
main.cpp
#include <iostream>
#include "tests.h"
int main() {
Tests tests = Tests();
tests.run();
return 0;
}
allocator.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;
}
tests.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;
}
allocator.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;
}
tests.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); 行之后的所有couts 都被忽略,这意味着该构造函数调用有问题。不过,我不知道到底是什么。
有人可以帮我解决这个问题吗?
附:如果您碰巧注意到任何其他错误或严重错误(我怀疑有一些),请告诉我。谢谢
【问题讨论】:
-
Allocator::Allocator() { Allocator(100); }不会做你期望它做的事情:它创建一个临时的,在离开构造函数后立即被销毁 - 并使你的构造对象未初始化。您很可能想要构造函数委托:Allocator() : Allocator(100) { } -
Allocator::Allocator取消引用head指针而不对其进行初始化。 -
如果您碰巧注意到任何其他错误或严重错误 好吧,除非这是一个错字
Allocator::Allocator() { Allocator(100); },否则如果您打算这样做,则永远不应该写一些高级的东西,比如创建一个分配器。 -
dl_l new_block; /* ... */ add_to_list(ptr->prev, &new_block, ptr);– 添加一个指向局部变量的指针,该变量将在退出函数时被销毁 – 在列表中留下一个悬空指针... -
@OP -- 为什么我的印象是你正在尝试使用另一种语言(可能是 Java)作为指导来编写 C++?这永远不会成功。
标签: c++ memory memory-management allocator