c++ 内存管理 3 malloc/free 的简单实现(隐式链表/显式链表)

malloc/free

#include <iostream>
#include <cstdint>

using namespace std;

int main(int argc, char *argv[]) {
  int b1[4]{1, 2, 3, 4}; // 16 align
  int b2[5]{5, 4, 3, 2, 1};

  cout << b1 << " " << b2 << endl;

  //cout << sizeof(int) << endl; // 4
  cout << *(int *)((uint64_t)&b2 - sizeof(int)) << endl;

  return 0;
}

#include <iostream>
#include <cstdint>

using namespace std;

int main(int argc, char *argv[]) {

  int* p = (int *)malloc(4 * sizeof(int)); // p 在 stack上

  // 但以下数据在heap上
  p[0] = 1;
  p[1] = 1;
  p[2] = 1;
  p[3] = 1;

  free(p);

  return 0;
}

const char * 与 char *const

#include <iostream>
#include <cstdlib>
#include <cstdint>

using namespace std;

int main(int argc, char *argv[]) {

  char * const p = "hello world\0";
  const char * str = (char *)malloc(6);

  //p = str;
  //*(str+1) = 'l';
  str = p;

  cout << p << endl;
  cout << str << endl;

  return 0;
}

#include <iostream>
#include <cstdlib>
#include <cstdint>

using namespace std;

int main(int argc, char *argv[]) {

  char * str = (char *)malloc(6);
  str = "hello\0";


// size = 16 = 8 * 2 byte = 0x0000 0010
//  0000 0000
//  0000 0000
//  0000 0000
//  0000 0000
//  0000 0000
//  0000 0000
//  '\0'
//  'o'
//  ========= 8 byte对齐
//  'l'
//  'l'
//  'e'
//  'h'
//  0000 0000
//  0000 0000
//  0000 0000
//  0001 0001

//  6 / 16 = 0.375

  cout << str << endl;

  return 0;
}

heap 就是一个大数组

extern uint64_t heap_start_vaddr;
extern uint64_t heap_end_vaddr;

#define HEAP_MAX_SIZE (4096 * 1024) // 4MB
extern uint8_t heap[HEAP_MAX_SIZE];
#ifndef ALLOCATOR_H_
#define ALLOCATOR_H_

#include <alloca.h>
#include <cstdint>
#include <stdint.h>

extern uint64_t heap_start_vaddr;
extern uint64_t heap_end_vaddr;

#define HEAP_MAX_SIZE (4096 * 1024) // 4MB
extern uint8_t heap[HEAP_MAX_SIZE];

#define FREE (0)
#define ALLOCATED (1)
#define NIL (0)

#define MIN_EXPLICIT_FREE_LIST_BLOCKSIZE (16)
#define MIN_READBLACK_TREE_BLOCKSIZE (24)

// to allocate on physical page for heap(申请一个页表)
uint32_t extend_heap(uint32_t size);
void os_syscall_brk();

// round up
uint64_t round_up(uint64_t x, uint64_t n);

/*
 * operations for all blocks
 * */
// 获取/设置 blocksize
uint32_t get_blocksize(uint64_t header_vaddr);
void set_blocksize(uint64_t header_vaddr, uint32_t blocksize);

// 获取/设置 分配状态
uint32_t get_allocated(uint64_t header_vaddr);
void set_allocated(uint64_t header_vaddr, uint32_t allocated);

// 获取cookies
uint64_t get_payload(uint64_t vaddr);
uint64_t get_header(uint64_t vaddr);
uint64_t get_footer(uint64_t vaddr);

/*
 * operations for heap linked list
 * */

uint64_t get_nextheader(uint64_t vaddr);
uint64_t get_prevheader(uint64_t vaddr);

uint64_t get_prologue(); // 前言
uint64_t get_epilogue(); // 后记

uint64_t get_firstblock();
uint64_t get_lastblock();

int is_lastblock(uint64_t vaddr);
int is_firstblock(uint64_t vaddr);

// for free block as data structure
uint64_t get_field32_block_ptr(uint64_t header_vaddr, uint32_t min_blocksize,
                               uint32_t offset);
void set_field32_block_ptr(uint64_t header_vaddr, uint64_t block_ptr,
                           uint32_t min_blocksize, uint32_t offset);

// interface
int heap_init();
uint64_t mem_alloc(uint32_t size);
void mem_free(uint64_t vaddr);

#endif // ALLOCATOR_H_

block 的结构

高位
 ____________________
|___blocksize__|_A/F_| <- footer
|                    |
|                    |
|      payload       |
|                    |
|____________________|
|___blocksize__|_A/F_| <- header

低位

// start_of_heap
// (heap_start_vaddr)| [4(padding)] ->[8(header+footer)] [...]

// end_of_heap
// (heap_start_vaddr)| [4(padding)] [8(header+footer)] [...] ->[header] |(heap_end_vaddr)
 
#include "allocator.h"
#include <cassert>
#include <cstdint>
#include <iostream>

#define AF_BIT (0) // ALLOCATED / FREE
#define P8_BIT (1) // PREV BLOCK is a BLOCK 8
#define B8_BIT (2) // THIS BLOCK is 8 bytes


uint64_t round_up(uint64_t x, uint64_t n) { return n * ((x + n - 1) / n); }

// 设置第n位为1 H >> L
static void set_bit(uint64_t vaddr, int bit_offset) {
  uint32_t vector = 1 << bit_offset; // 000...1...000
  assert((vaddr & 0x3) == 0);        // 4对齐
  assert(get_prologue() <= vaddr && vaddr <= get_epilogue());
  *(uint32_t *)&heap[vaddr] |= vector;
}

// 将第n位清零 H >> L
static void reset_bit(uint64_t vaddr, int bit_offset) {
  uint32_t vector = 1 << bit_offset; // 000...1...000
  assert((vaddr & 0x3) == 0);        // 4对齐
  assert(get_prologue() <= vaddr && vaddr <= get_epilogue());
  *(uint32_t *)&heap[vaddr] &= (~vector); // 111...0...111
}

// 检查第n位是否为1 H >> L
static int is_bit_set(uint64_t vaddr, int bit_offset) {
  assert((vaddr & 0x3) == 0); // 4对齐
  assert(get_prologue() <= vaddr && vaddr <= get_epilogue());
  return (*(uint32_t *)&heap[vaddr] >> bit_offset) & 1;
}

static int is_block8(uint64_t vaddr) {
  if (vaddr == NIL || vaddr == get_epilogue()) {
    return 0;
  }
  assert(get_prologue() <= vaddr && vaddr <= get_epilogue());

  if (vaddr % 8 == 4) {
    // header
    if (is_bit_set(vaddr, B8_BIT) == 1) {
      return 1;
    }
  } else if (vaddr % 8 == 0) {
    // footer
    uint64_t next_header = vaddr + 4; // 下一个block的header_vaddr
    if (is_bit_set(next_header, B8_BIT) == 1) {
      return 1;
    }
  }
  return 0;
}

// start_of_heap
// (heap_start_vaddr)| [4(padding)] ->[8(header+footer)] [...]
uint64_t get_prologue() {
  assert(heap_end_vaddr > heap_start_vaddr);
  assert((heap_end_vaddr - heap_start_vaddr) % 4096 == 0); // 检查是否4k对齐
  assert(heap_start_vaddr % 4096 == 0);

  return heap_start_vaddr + sizeof(uint32_t);
}

// end_of_heap
// (heap_start_vaddr)| [4(padding)] [8(header+footer)] [...] ->[header]
// |(heap_end_vaddr)
uint64_t get_epilogue() {
  assert(heap_end_vaddr > heap_start_vaddr);
  assert((heap_end_vaddr - heap_start_vaddr) % 4096 == 0); // 检查是否4k对齐
  assert(heap_start_vaddr % 4096 == 0);

  return heap_end_vaddr - sizeof(uint32_t);
}

uint32_t get_blocksize(uint64_t header_vaddr) {
  if (header_vaddr == NIL) {
    return 0;
  }

  assert(get_prologue() <= header_vaddr &&
         header_vaddr <= get_epilogue()); // 在可用范围内
  assert((header_vaddr & 0x3) == 0x0);

  if (is_block8(header_vaddr) == 1) {
    return 8;
  } else {
    return (*((uint32_t *)&heap[header_vaddr]) &
            0xFFFFFFF8); // 000 prev_block_is_block_8| block_8| a/f
  }
}

void set_blocksize(uint64_t header_vaddr, uint32_t blocksize) {
  if (header_vaddr == NIL) {
    return;
  }
  assert(get_prologue() <= header_vaddr &&
         header_vaddr <= get_epilogue()); // 在可用范围内
  assert((header_vaddr & 0x3) == 0x0);
  assert((blocksize & 0x7) == 0x0);

  uint64_t next_header_vaddr;
  if (blocksize == 8) {
    // small block is special
    if (header_vaddr % 8 == 0) {
      // do not set footer of small block
      //  '\0'
      //  'a'
      //  'a'
      //  'a'
      //  0000 0000
      //  0000 0000
      //  0000 0000
      //  0100 0001 size == 8 这种就不设置footer了
      // reset to header
      header_vaddr = header_vaddr - 4;
    }
    next_header_vaddr = header_vaddr + 8;

    set_bit(header_vaddr, B8_BIT); // 设置该block的 8byte属性
    if (next_header_vaddr <= get_epilogue()) {
      set_bit(next_hea
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值