前言
侯捷的这本《STL源码剖析》读本科的时候就拿来膜拜过,但是看不懂。
然后就放弃了,这段时间用STL比较多,上周碰到了一系列问题。
1.需要自定义一个配置器或者自定义一个vector
因为,STL默认的配置器没有及时释放内存,当时线上内存使用已超过10g,其中有一半是可以释放的。
2.使用swap再加上自定义的配置器(使用malloc和free),即便如此进程仍没有把内存归还给OS。
通过进一步对比分析,推测很可能是linux中的glibc的缘故,它是管理内存的,介于OS和STL之间。它没有将内存还给OS。
3.关于map容器的多线程访问。
理论上STL中的容器,多线程读应该是安全的,但是实践中发现使用[]多线程读map会出现问题,后改用find后就没问题了。
事实上,我用[]读map的时候,有的key是不存在的,在这种情况下,我不知道STL会做了什么从而导致了多线程读出问题。
仅仅知道map的底层是用红黑树实现是不够的。
带着这些问题我觉的有必要看下这本书。希望通过这次阅读能知道STL做了什么,书上用的好像是windows下的STL,我搜了下
linux下的STL应该是在bin/usr下面。我这C++的版本是 gcc version 4.4.6 20110731 (Red Hat 4.4.6-3)
还是老习惯,这本书我不会一口气全看完,具体读哪些,视情况而定,从第二章开始。另外如果有机会的话,再看下《effect STL》
两本书都是电子版的,想要的朋友可以联系我,好了废话不多说了,开始吧。
第2章 空间配置器(allocator)
2.1.allocator的意义
配置STL中容器的空间,主要指内存,负责申请和释放。
2.2.allocator的形式
allocator里面有一大堆东西,在不知道需求之前看到这一堆东西是很难理解的。
allocator的重点是allocate,deallocate,construct,destroy 请看一个例子:
1 StlAllocator 2 template<typename Type> 3 class StlAllocator 4 { 5 public: 6 typedef Type value_type; 7 typedef value_type* pointer; 8 typedef const value_type* const_pointer; 9 typedef value_type& reference; 10 typedef const value_type& const_reference; 11 typedef std::size_t size_type; 12 typedef std::ptrdiff_t difference_type; 13 public: 14 template<typename U> 15 struct rebind 16 { 17 typedef StlAllocator<U> other; 18 }; 19 public: 20 inline StlAllocator() {} 21 inline ~StlAllocator() {} 22 inline StlAllocator(StlAllocator const&) {} 23 template<typename U> 24 inline StlAllocator(StlAllocator<U> const&) {} 25 inline pointer address(reference r) { return &r; } 26 inline const_pointer address(const_reference r) { return &r; } 27 inline pointer allocate( size_type cnt, typename std::allocator<void>::const_pointer = 0 ) 28 { 29 return (pointer) malloc( cnt * sizeof(Type) ); 30 } 31 inline void deallocate( pointer p, size_type size ) 32 { 33 free(p); 34 } 35 inline size_type max_size() const 36 { 37 return std::numeric_limits<size_type>::max() / sizeof(Type); 38 } 39 inline void construct(pointer p, const Type& t) { new(p) Type(t); } 40 inline void destroy(pointer p) { p->~Type(); } 41 inline bool operator==(StlAllocator const&) const { return true; } 42 inline bool operator!=(StlAllocator const& a) const { return !operator==(a); } 43 };
书上讲了很多,总体上就是内置的配置器有两种内存申请方式。
1.申请的内存大于128B,此时用的是普通的malloc和free
2.其它的从一个特殊的链表上获取,链表上挂着不同大小的可利用内存块,这些块是从内存池中获取的,内存池是事前分配的,不够了会向系统再申请。
对于方式1,free了以后就释放了,对于方式2,释放了以后是还给了这个特殊的链表。
感兴趣的可以实践下,构造一个vector< vector<char> >,更改里面的vector长度,代码如下:
1 #include <vector> 2 #include <iostream> 3 #include <ctime> 4 using namespace std; 5 6 int main() 7 { 8 vector< vector<char> > data; 9 data.resize(1000000); 10 for (int i = 0 ;i < data.size(); i ++) 11 data[i].resize(120); 12 13 cout << "release befor" << endl; 14 sleep(10); 15 vector< vector<char> >().swap(data); 16 cout << "release after" << endl; 17 sleep(10); 18 return 0; 19 }
无论外面的vector多大,能不能释放还是里面的vector大小决定的