3

C++ は初めてです。このバディ システム メモリ割り当てのコードを見つけましたが、メイン関数がありません。すべてのメンバー関数は正しいです。メイン関数を手伝ってほしいです。メモリを割り当てて、その状態を表示したいです。割り当て前後のメモリを確認し、メモリの割り当てを解除してバディがマージされていることを確認し、空きブロックのリストを表示します

--BuddyPool.h--

#ifndef  BUDDYPOOL_INC
#define  BUDDYPOOL_INC

class BuddyPool{
public:
    enum Status { free, reserved };
    struct Header
    {
        Status status: 1;
        //unsigned int k : bitsizeof(unsigned int) - 1U;
        unsigned int k : 31;
    };
    struct Block : public Header
    {
        //enum { size = 16 };

        enum { size = 64 };
        struct Links
        {
            Block *next;
            Block *prev;
        };
        union
        {
            Links link;
            char userPart [size - sizeof(Header)];
        };
    };

private:
    unsigned int m;
    unsigned int numberOfBlocks;
    Block *pool;
    Block *sentinel;

    static void Unlink(Block &);
    static void InsertAfter(Block &, Block &);
    Block &Buddy(Block &) const;

public:
    BuddyPool(size_t);
    ~BuddyPool();

    void *Acquire(size_t);
    void Release(void *);
};

#endif   /* ----- #ifndef BUDDYPOOL_INC  ----- */

--BuddyPool.cpp--

#include <WinDef.h>
#include "BuddyPool.h"

unsigned int Log2Ceil(unsigned int val){
    unsigned int L;
    for (L = 0; (1ul<<L) < val; L++);
    return L;
}

BuddyPool::BuddyPool(size_t bytes) 
    : m(Log2Ceil(bytes))
    , numberOfBlocks( (1 << m) / sizeof(Block))
    , pool (new Block[numberOfBlocks + m +1])
    , sentinel(pool + numberOfBlocks)
{
    for (unsigned int i = 0; i <= m; ++i) {
        sentinel[i].link.next = &sentinel[i];
        sentinel[i].link.prev = &sentinel[i];
    }

    Block &head = pool[0];
    head.status = free;
    head.k = m;
    InsertAfter(sentinel[m], head);
}

BuddyPool::~BuddyPool(){
    delete [] pool;
}

void *BuddyPool::Acquire(size_t bytes){
    unsigned int kPrime = Log2Ceil(bytes + sizeof(Header));

    unsigned int i = kPrime;
    while (i <= m && sentinel[i].link.next == &sentinel[i]) {
        ++i;
    }
    if (i > m) {
        return NULL;    // throw bad_alloc("out of memory");
    }

    Block &block = *sentinel[i].link.next;
    Unlink(block);
    while (block.k > kPrime) {
        block.k -= 1;
        Block &buddy = Buddy(block);
        buddy.status = free;
        buddy.k = block.k;
        InsertAfter(sentinel[buddy.k], buddy);
    }
    block.status = reserved;
    return block.userPart;
}

void BuddyPool::Release(void *arg){
    Block &block = *reinterpret_cast<Block *>(
                                              reinterpret_cast<Header *>(arg) - 1U);

    if (&block < pool || &block >= pool + numberOfBlocks) {
        return; // throw invalid_argument("invalid pointer");
    }

    block.status = free;
    Block *ptr;
    for (ptr = &block; ptr->k < m; ptr->k += 1) {
        Block &buddy = Buddy(*ptr);
        if (buddy.status == reserved || buddy.k != ptr->k) {
            break;
        }
        Unlink(buddy);
        if (&buddy < ptr) {
            ptr = &buddy;
        }
    }

    InsertAfter(sentinel[ptr->k], *ptr);
}

BuddyPool::Block &BuddyPool::Buddy(Block &block) const{
    unsigned int addr = reinterpret_cast<unsigned int>(&block) + (1 << block.k);
    return *(reinterpret_cast<Block *>(addr));
}

void BuddyPool::Unlink(Block &block){
    if (block.link.next) {
        block.link.next->link.prev = block.link.prev;
    }
    if (block.link.prev) {
        block.link.prev->link.next = block.link.next;
    }
    block.link.next = block.link.prev = &block;
}

void BuddyPool::InsertAfter(Block &src, Block &block){
    block.link.next = src.link.next;
    block.link.prev = &src;

    if (src.link.next) {
        src.link.next->link.prev = &block;
    }
    src.link.next = &block; 
}
4

1 に答える 1

3

パブリック関数を呼び出すだけで開始できます。

内部活動を視覚化するのはかなり困難です。それに対する簡単な答えはありません。Python などの一部の言語では、ビジュアライザーがあり、オンライン ビジュアライザーもあります。

より高度な使用法: 呼び出しを標準のアロケータ クラス (「 」を参照std::allocator) でラップします。これを使用して、たとえば a の割り当てと割り当て解除を行うことができますstd::vector

および/またはいくつかのクラスに対してoperator newand operator delete(それぞれ単一のオブジェクト割り当ておよび解放関数) を定義できます。

于 2013-02-22T10:48:09.263 に答える