C++中内存池的简单原理及实现详解

为什么要用内存池

C++程序默认的内存管理(new,delete,malloc,free)会频繁地在堆上分配和释放内存,导致性能的损失,产生大量的内存碎片,降低内存的利用率。默认的内存管理因为被设计的比较通用,所以在性能上并不能做到极致。

因此,很多时候需要根据业务需求设计专用内存管理器,便于针对特定数据结构和使用场合的内存管理,比如:内存池。

内存池原理

内存池的思想是,在真正使用内存之前,预先申请分配一定数量、大小预设的内存块留作备用。当有新的内存需求时,就从内存池中分出一部分内存块,若内存块不够再继续申请新的内存,当内存释放后就回归到内存块留作后续的复用,使得内存使用效率得到提升,一般也不会产生不可控制的内存碎片。

内存池设计

算法原理:

1.预申请一个内存区chunk,将内存中按照对象大小划分成多个内存块block

2.维持一个空闲内存块链表,通过指针相连,标记头指针为第一个空闲块

3.每次新申请一个对象的空间,则将该内存块从空闲链表中去除,更新空闲链表头指针

4.每次释放一个对象的空间,则重新将该内存块加到空闲链表头

5.如果一个内存区占满了,则新开辟一个内存区,维持一个内存区的链表,同指针相连,头指针指向最新的内存区,新的内存块从该区内重新划分和申请

如图所示:

内存池实现

memory_pool.hpp

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

#ifndef _MEMORY_POOL_H_

#define _MEMORY_POOL_H_

#include <stdint.h>

#include <mutex>

template<size_tBlockSize,size_tBlockNum = 10>

classMemoryPool

{

public:

MemoryPool()

{

std::lock_guard<std::mutex> lk(mtx);// avoid race condition

// init empty memory pointer

free_block_head = NULL;

mem_chunk_head = NULL;

}

~MemoryPool()

{

std::lock_guard<std::mutex> lk(mtx);// avoid race condition

// destruct automatically

MemChunk* p;

while(mem_chunk_head)

{

p = mem_chunk_head->next;

deletemem_chunk_head;

mem_chunk_head = p;

}

}

void* allocate()

{

std::lock_guard<std::mutex> lk(mtx);// avoid race condition

// allocate one object memory

// if no free block in current chunk, should create new chunk

if(!free_block_head)

{

// malloc mem chunk

MemChunk* new_chunk =newMemChunk;

new_chunk->next = NULL;

// set this chunk's first block as free block head

free_block_head = &(new_chunk->blocks[0]);

// link the new chunk's all blocks

for(inti = 1; i < BlockNum; i++)

new_chunk->blocks[i - 1].next = &(new_chunk->blocks[i]);

new_chunk->blocks[BlockNum - 1].next = NULL;// final block next is NULL

if(!mem_chunk_head)

mem_chunk_head = new_chunk;

else

{

// add new chunk to chunk list

mem_chunk_head->next = new_chunk;

mem_chunk_head = new_chunk;

}

}

// allocate the current free block to the object

void* object_block = free_block_head;

free_block_head = free_block_head->next;

returnobject_block;

}

void* allocate(size_tsize)

{

std::lock_guard<std::mutex> lk(array_mtx);// avoid race condition for continuous memory

// calculate objects num

intn = size / BlockSize;

// allocate n objects in continuous memory

// FIXME: make sure n > 0

void* p = allocate();

for(inti = 1; i < n; i++)

allocate();

returnp;

}

voiddeallocate(void* p)

{

std::lock_guard<std::mutex> lk(mtx);// avoid race condition

// free object memory

FreeBlock* block =static_cast<FreeBlock*>(p);

block->next = free_block_head;// insert the free block to head

free_block_head = block;

}

private:

// free node block, every block size exactly can contain one object

structFreeBlock

{

unsignedchardata[BlockSize];

FreeBlock* next;

};

FreeBlock* free_block_head;

// memory chunk, every chunk contains blocks number with fixed BlockNum

structMemChunk

{

FreeBlock blocks[BlockNum];

MemChunk* next;

};

MemChunk* mem_chunk_head;

// thread safe related

std::mutex mtx;

std::mutex array_mtx;

};

#endif // !_MEMORY_POOL_H_

main.cpp

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

#include <iostream>

#include "memory_pool.hpp"

classMyObject

{

public:

MyObject(intx): data(x)

{

//std::cout << "contruct object" << std::endl;

}

~MyObject()

{

//std::cout << "destruct object" << std::endl;

}

intdata;

// override new and delete to use memory pool

void* operatornew(size_tsize);

voidoperatordelete(void* p);

void* operatornew[](size_tsize);

voidoperatordelete[](void* p);

};

// define memory pool with block size as class size

MemoryPool<sizeof(MyObject), 3> gMemPool;

void* MyObject::operatornew(size_tsize)

{

//std::cout << "new object space" << std::endl;

returngMemPool.allocate();

}

voidMyObject::operatordelete(void* p)

{

//std::cout << "free object space" << std::endl;

gMemPool.deallocate(p);

}

void* MyObject::operatornew[](size_tsize)

{

// TODO: not supported continuous memoery pool for now

//return gMemPool.allocate(size);

returnNULL;

}

voidMyObject::operatordelete[](void* p)

{

// TODO: not supported continuous memoery pool for now

//gMemPool.deallocate(p);

}

intmain(intargc,char* argv[])

{

MyObject* p1 =newMyObject(1);

std::cout <<"p1 "<< p1 <<" "<< p1->data<< std::endl;

MyObject* p2 =newMyObject(2);

std::cout <<"p2 "<< p2 <<" "<< p2->data << std::endl;

deletep2;

MyObject* p3 =newMyObject(3);

std::cout <<"p3 "<< p3 <<" "<< p3->data << std::endl;

MyObject* p4 =newMyObject(4);

std::cout <<"p4 "<< p4 <<" "<< p4->data << std::endl;

MyObject* p5 =newMyObject(5);

std::cout <<"p5 "<< p5 <<" "<< p5->data << std::endl;

MyObject* p6 =newMyObject(6);

std::cout <<"p6 "<< p6 <<" "<< p6->data << std::endl;

deletep1;

deletep2;

//delete p3;

deletep4;

deletep5;

deletep6;

getchar();

return0;

}

运行结果

p1 00000174BEDE0440 1
p2 00000174BEDE0450 2
p3 00000174BEDE0450 3
p4 00000174BEDE0460 4
p5 00000174BEDD5310 5
p6 00000174BEDD5320 6

可以看到内存地址是连续,并且回收一个节点后,依然有序地开辟内存
对象先开辟内存再构造,先析构再释放内存

注意

  • 在内存分配和释放的环节需要加锁来保证线程安全
  • 还没有实现对象数组的分配和释放

https://gitee.com/sdger1/gfd/blob/master/IUbeb.md
https://gitee.com/sdger1/gfd/blob/master/gFQji.md
https://gitee.com/sdger1/gfd/blob/master/NGqDL.md
https://gitee.com/sdger1/gfd/blob/master/VmTsR.md
https://gitee.com/sdger1/gfd/blob/master/iODwe.md
https://gitee.com/sdger1/gfd/blob/master/OaxTf.md
https://gitee.com/sdger1/gfd/blob/master/xHOGb.md
https://gitee.com/sdger1/gfd/blob/master/sltat.md
https://gitee.com/sdger1/gfd/blob/master/ssipT.md
https://gitee.com/sdger1/gfd/blob/master/ZUuiD.md
https://gitee.com/sdger1/gfd/blob/master/zJUvh.md
https://gitee.com/sdger1/gfd/blob/master/PNTWl.md
https://gitee.com/sdger1/gfd/blob/master/PsIep.md
https://gitee.com/sdger1/gfd/blob/master/mHSIE.md
https://gitee.com/sdger1/gfd/blob/master/cVqSE.md
https://gitee.com/sdger1/gfd/blob/master/meOOp.md
https://gitee.com/sdger1/gfd/blob/master/otVqz.md
https://gitee.com/sdger1/gfd/blob/master/jRvhC.md
https://gitee.com/sdger1/gfd/blob/master/SYHiR.md
https://gitee.com/sdger1/gfd/blob/master/CPXGd.md
https://gitee.com/sdger1/gfd/blob/master/xqItR.md
https://gitee.com/sdger1/gfd/blob/master/sbGBK.md
https://gitee.com/sdger1/gfd/blob/master/oVDbK.md
https://gitee.com/sdger1/gfd/blob/master/hcTzi.md
https://gitee.com/sdger1/gfd/blob/master/jUICZ.md
https://gitee.com/sdger1/gfd/blob/master/itnJK.md
https://gitee.com/sdger1/gfd/blob/master/bXswt.md
https://gitee.com/sdger1/gfd/blob/master/bjYJd.md
https://gitee.com/sdger1/gfd/blob/master/KXqmy.md
https://gitee.com/sdger1/gfd/blob/master/laLWX.md
https://gitee.com/sdger1/gfd/blob/master/Auddm.md
https://gitee.com/sdger1/gfd/blob/master/nIwVc.md
https://gitee.com/sdger1/gfd/blob/master/NAaOE.md
https://gitee.com/sdger1/gfd/blob/master/ZwWFg.md
https://gitee.com/sdger1/gfd/blob/master/VcSOW.md
https://gitee.com/sdger1/gfd/blob/master/QuUmw.md
https://gitee.com/sdger1/gfd/blob/master/xdBXL.md
https://gitee.com/sdger1/gfd/blob/master/APGaU.md
https://gitee.com/sdger1/gfd/blob/master/hfeOb.md
https://gitee.com/sdger1/gfd/blob/master/GqQZJ.md
https://gitee.com/sdger1/gfd/blob/master/tPZOM.md
https://gitee.com/sdger1/gfd/blob/master/LyyhN.md
https://gitee.com/sdger1/gfd/blob/master/rbLLV.md
https://gitee.com/sdger1/gfd/blob/master/ySagR.md
https://gitee.com/sdger1/gfd/blob/master/iOaQl.md
https://gitee.com/sdger1/gfd/blob/master/ntgWQ.md
https://gitee.com/sdger1/gfd/blob/master/BDPyQ.md
https://gitee.com/sdger1/gfd/blob/master/STISE.md
https://gitee.com/sdger1/gfd/blob/master/keNlX.md
https://gitee.com/sdger1/gfd/blob/master/pZhlh.md
https://gitee.com/sdger1/gfd/blob/master/NfStS.md
https://gitee.com/sdger1/gfd/blob/master/xsLJG.md
https://gitee.com/sdger1/gfd/blob/master/GmvQi.md
https://gitee.com/sdger1/gfd/blob/master/OhZkn.md
https://gitee.com/sdger1/gfd/blob/master/lUnPw.md
https://gitee.com/sdger1/gfd/blob/master/JCtsK.md
https://gitee.com/sdger1/gfd/blob/master/zWJqZ.md
https://gitee.com/sdger1/gfd/blob/master/dybxu.md
https://gitee.com/sdger1/gfd/blob/master/ircGP.md
https://gitee.com/sdger1/gfd/blob/master/SLtgb.md
https://gitee.com/sdger1/gfd/blob/master/kfVFz.md
https://gitee.com/sdger1/gfd/blob/master/jsHfF.md
https://gitee.com/sdger1/gfd/blob/master/hscdn.md
https://gitee.com/sdger1/gfd/blob/master/vKfEU.md
https://gitee.com/sdger1/gfd/blob/master/nkFDa.md
https://gitee.com/sdger1/gfd/blob/master/QhKht.md
https://gitee.com/sdger1/gfd/blob/master/SdDPc.md
https://gitee.com/sdger1/gfd/blob/master/GJIEH.md
https://gitee.com/sdger1/gfd/blob/master/NsLGU.md
https://gitee.com/sdger1/gfd/blob/master/EUdkX.md
https://gitee.com/sdger1/gfd/blob/master/DOlhD.md
https://gitee.com/sdger1/gfd/blob/master/FscsK.md
https://gitee.com/sdger1/gfd/blob/master/AIpBc.md
https://gitee.com/sdger1/gfd/blob/master/hpYLZ.md
https://gitee.com/sdger1/gfd/blob/master/dJcDk.md
https://gitee.com/sdger1/gfd/blob/master/AramM.md
https://gitee.com/sdger1/gfd/blob/master/DQDyw.md
https://gitee.com/sdger1/gfd/blob/master/kicEg.md
https://gitee.com/sdger1/gfd/blob/master/NWFGp.md
https://gitee.com/sdger1/gfd/blob/master/pyPQq.md
https://gitee.com/sdger1/gfd/blob/master/miVts.md
https://gitee.com/sdger1/gfd/blob/master/BDWNq.md
https://gitee.com/sdger1/gfd/blob/master/cywIV.md
https://gitee.com/sdger1/gfd/blob/master/fYcDo.md
https://gitee.com/sdger1/gfd/blob/master/NUmLu.md
https://gitee.com/sdger1/gfd/blob/master/KAvgp.md
https://gitee.com/sdger1/gfd/blob/master/ijXsJ.md
https://gitee.com/sdger1/gfd/blob/master/XpMox.md
https://gitee.com/sdger1/gfd/blob/master/abOwN.md
https://gitee.com/sdger1/gfd/blob/master/qydmX.md
https://gitee.com/sdger1/gfd/blob/master/hPOiU.md
https://gitee.com/sdger1/gfd/blob/master/grvVT.md
https://gitee.com/sdger1/gfd/blob/master/owqfj.md
https://gitee.com/sdger1/gfd/blob/master/tawNi.md
https://gitee.com/sdger1/gfd/blob/master/dfmlf.md
https://gitee.com/sdger1/gfd/blob/master/GyeSj.md
https://gitee.com/sdger1/gfd/blob/master/HBbcU.md
https://gitee.com/sdger1/gfd/blob/master/ztFuV.md
https://gitee.com/sdger1/gfd/blob/master/JXGVb.md
https://gitee.com/sdger1/gfd/blob/master/TznMi.md
https://gitee.com/sdger1/gfd/blob/master/AWtsK.md
https://gitee.com/sdger1/gfd/blob/master/jXMvJ.md
https://gitee.com/sdger1/gfd/blob/master/CvUMt.md
https://gitee.com/sdger1/gfd/blob/master/MFoeB.md
https://gitee.com/sdger1/gfd/blob/master/jQXwi.md
https://gitee.com/sdger1/gfd/blob/master/tEmYe.md
https://gitee.com/sdger1/gfd/blob/master/TOcZV.md
https://gitee.com/sdger1/gfd/blob/master/bdFww.md
https://gitee.com/sdger1/gfd/blob/master/lRAVz.md
https://gitee.com/sdger1/gfd/blob/master/PCeiD.md
https://gitee.com/sdger1/gfd/blob/master/nWGbq.md
https://gitee.com/sdger1/gfd/blob/master/VOWYU.md
https://gitee.com/sdger1/gfd/blob/master/jjolD.md
https://gitee.com/sdger1/gfd/blob/master/fmvxV.md
https://gitee.com/sdger1/gfd/blob/master/KEebL.md
https://gitee.com/sdger1/gfd/blob/master/bUUMd.md
https://gitee.com/sdger1/gfd/blob/master/OJUFd.md
https://gitee.com/sdger1/gfd/blob/master/ywaAt.md
https://gitee.com/sdger1/gfd/blob/master/LpepO.md
https://gitee.com/sdger1/gfd/blob/master/zxQSp.md
https://gitee.com/sdger1/gfd/blob/master/MlXGo.md
https://gitee.com/sdger1/gfd/blob/master/FpnAd.md
https://gitee.com/sdger1/gfd/blob/master/keBpq.md
https://gitee.com/sdger1/gfd/blob/master/OyoZb.md
https://gitee.com/sdger1/gfd/blob/master/ooKHv.md
https://gitee.com/sdger1/gfd/blob/master/SqqOG.md
https://gitee.com/sdger1/gfd/blob/master/SFPXh.md
https://gitee.com/sdger1/gfd/blob/master/lVgFB.md
https://gitee.com/sdger1/gfd/blob/master/gJHRS.md
https://gitee.com/sdger1/gfd/blob/master/YLFfy.md
https://gitee.com/sdger1/gfd/blob/master/yIEYN.md
https://gitee.com/sdger1/gfd/blob/master/XYiSn.md