内存管理
内存管理是一个很深刻的话题, 对于初学者来说, 内存管理看不到摸不着, 我们常使用 new / delete 来管理我们的堆内存. 仅此而已.
本文记录了侯捷老师内存管理课程的学习笔记以及部分自己写的代码.
目的是了解C++如何进行内存管理, 剖析源码, 能够设计自己的内存池.
C++中内存管理工具
分配 |
释放 |
类型 |
是否可以重载 |
malloc() |
free() |
C函数 |
不可以 |
new |
delete |
C++表达式 |
不可以 |
::operator new() |
::operator delete() |
C++函数 |
可以 |
allocator<T>::allocate() |
allocator<T>::deallocate() |
C++标准库 |
可自由设计并搭配容器 |
用法示例
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
| void* p1 = malloc(512); free(p1);
complex<int>* p2 = new complex<int>; delete p2;
void* p3 = ::operator new(512); ::operator delete(p3);
#ifdef __GUNC__
void* p4 = alloc::allocate(512); alloc::deallocate(p4,512);
#endif
#ifdef __GNUC__
void* p4 = allocator<int>().allocate(7); allocator<int>().deallocate((int*)p4, 7); void* p5 = __gnu_cxx::__pool_alloc<int>().allocate(9); __gnu_cxx::__pool_alloc<int>().deallocate((int*)p5, 9); #endif
|
new 运算符
1 2 3 4 5 6 7 8 9 10 11 12 13
| Complex* pc = new Complex(1,2);
编译器转换→
Complex *pc; try{ void* mem = operator new(sizeof(Complex)); pc = static_cast<Complex*>(mem); pc->Complex::Complex(1,2); } catch (std::bad_alloc) { }
|
operator new() vc98默认版本
1 2 3 4 5 6 7 8 9 10 11 12
| void * operator new(size_t size, const std::nothrow t&) _THROW0() { void *p; while((p == malloc(size)) == 0){ _TRY_BEGIN if(_callnewh(size) == 0) break; _CATCH(std::bad_alloc) return 0; _CATCH_END } return (p); }
|
delete 运算符
1 2 3 4 5 6 7 8
| Complex* pc = new Complex(1,2); ... delete pc;
编译器转换->
pc->~Complex(); operator delete(pc);
|
operator delete() vc98默认版本
1 2 3 4
| void __cdecl operator delete(void * p) _THROW0() { free(p); }
|
array new / array delete
1 2 3 4
| Complex * pca = new Complex[3];
... delete [] pca;
|
内存分配的时候, 头部会有 cookie 方便回收.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| int * pi = new int[10]; delete pi;
vc6 : cookie 61h(记录大小是60字节,1表示使用了这一块) Debugger Header(32 Bytes) int int int ... int no man land Pad(12 Bytes) 61h
|
placement new
允许我们在已经申请的堆内存上, 构建一个对象.
placement new 没有对应的 placement delete, 因为 placement new操作并没有分配内存.
1 2 3 4 5 6 7 8 9 10 11 12 13
| char * buf = new char[sizeof(Complex)*3]; Complex * pc = new (buf) Complex(1,2); ... delete [] buf;
编译器->
Complex * pc; try { void * mem = operator new(sizeof(Complex), buf); pc = static_cast<Complex*>(mem); pc->Complex::Complex(1,2); }
|
C++应用程序分配内存的途径
应用程序
1 2 3 4 5 6 7 8 9 10
| Foo *p = new Foo(x); delete p;
编译器->不可以改变不可以重载
Foo *p = (Foo*)operator new(sizeof(Foo)); new (p) Foo(x);
p->~Foo(); operator delete(x);
|
operator new / operator delete
1 2 3 4 5 6 7
| Foo *p = (Foo*)operator new(sizeof(Foo)); 调用 -> ::operator new(size_t); 调用 -> malloc(size_t);
operator delete(x); 调用 -> ::operator delete(void*); 调用 -> free(void*);
|
在类中重载 operator new
和 operator delete
1 2 3 4 5
| Foo *p = (Foo*)operator new(sizeof(Foo)); 重载 Foo::operator new(size_t); -> 调用 ::operator new(size_t);
operator delete(x); 重载 Foo::operator delete(void*); -> 调用 ::operator delete(void*);
|
C++容器分配内存的途径
容器
1 2 3 4 5
| T *p = allocate(); construct();
destroy(); deallocate(p);
|
分配器
1 2 3
| allocate(); deallocate(); 调用 -> ::operator new or ::operator delete
|
重载 ::operator new / ::operator delete
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
| void * myAlloc(size_t size){ return malloc(size); }
void myFree(void * ptr){ return free(ptr); }
inline void * operator new(size_t size){ cout << "global new()" << endl; return myAlloc(size); }
inline void * operator new[](size_t size){ cout << "global new[]" << endl; return myAlloc(size); }
inline void operator delete(void * ptr){ cout << "global delete()" << endl; myFree(ptr); }
inline void operator delete[](void * ptr){ cout << "global delete[]" << endl; myFree(ptr); }
|
重载 operator new / operator delete
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Foo { public: void * operator new(size_t); void operator delete(void *, size_t); };
Foo *p = new Foo; 编译器-> try { void * mem = operator new(sizeof(Foo)); p = static_cast<Foo*>(mem); p->Foo::Foo(1,2); }
delete p; 编译器-> p->~Foo(); operator delete(p);
|
重载 placement new / placement delete
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
| class Foo {
void * operator new(size_t size){ return malloc(size); }
void * operator new(size_t size, void * start){ return start; }
void * operator new(size_t size, long extra){ return malloc(size + extra); }
void * operator new(size_t size, long extra, char init){ return malloc(size + extra); }
};
|