A wrapper of SGI STL memory allocator and deallocator
2008-03-08 09:01
477 查看
This article gives a wrapper of the SGI STL memory allocator and deallocator, providing a powerful tool for your own use directly. The header files needed are "alloc.h", "stl_config.h" and "stl_alloc.h". The last two are used within the library itself. We had better not use the memebers defined in them directly. Thus, If you are already using a C++ compiler supporting SGI STL, then just include "alloc.h" at the beginning of your files.
The allocator we are going to use is __default_alloc_template, which deals with small block allocation. It will check the requested size first. If it exceeds some given size, in SGI STL which is 128 bytes, it will call __malloc_alloc_template to deal with it. Our wrapper here, MemoryPool, is also designed with template parameters, in order to be general for all the cases. The following code shows how it is implemented.
//MemoryPool.h
#ifndef _MEMORY_POOL_H
#define _MEMORY_POOL_H
#include <cstddef>
// make sure that stl_config.h, stl_alloc.h and alloc.h
// can be seen by the compiler, and it is better to
// put them in the user's current directory
#include "alloc.h"
template <typename T>
class MemoryPool ...{
public:
MemoryPool() : obj_size(sizeof(T)), block_size(16) ...{}
~MemoryPool() ...{}
void * Alloc(size_t);
void Free(void *, size_t);
public:
size_t obj_size, block_size;
};
template <typename T>
void * MemoryPool<T>::Alloc(size_t size) ...{
return __default_alloc_template<false, 0>::allocate(size);
}
template <typename T>
void MemoryPool<T>::Free(void * dead, size_t size) ...{
__default_alloc_template<false, 0>::deallocate(dead, size);
}
#endif
The classes AirplaneWithPool and AirplaneReq are still used here.
//AirplaneWithPool.h
#ifndef _AIRPLANE_WITH_POOL_H
#define _AIRPLANE_WITH_POOL_H
#include "MemoryPool.h"
#include <cstddef>
class AirplaneReq ...{
};
class AirplaneWithPool ...{
public:
static void * operator new(size_t);
static void operator delete(void *, size_t);
public:
AirplaneReq * req;
static MemoryPool<AirplaneWithPool> mem_pool;
};
#endif
//AirplaneWithPool.cpp
#include "AirplaneWithPool.h"
#include "MemoryPool.h"
MemoryPool<AirplaneWithPool> AirplaneWithPool::mem_pool;
void * AirplaneWithPool::operator new(size_t size) ...{
return mem_pool.Alloc(size);
}
void AirplaneWithPool::operator delete(void * dead_object, size_t size) ...{
mem_pool.Free(dead_object, size);
}
//item10WithPool.cpp
#include "AirplaneWithPool.h"
#include <iostream>
using namespace std;
int main() ...{
#ifdef __STL_USE_NAMESPACES
cout << "malloc" << endl;
#else
cout << "default" << endl;
#endif
AirplaneWithPool * apwp0 = new AirplaneWithPool();
cout << "apwp0: " << apwp0 << endl;
AirplaneWithPool * apwp1 = new AirplaneWithPool();
cout << "apwp1: " << apwp1 << endl;
AirplaneWithPool * apwp2 = new AirplaneWithPool();
cout << "apwp2: " << apwp2 << endl;
delete apwp1;
AirplaneWithPool * apwp3 = new AirplaneWithPool();
cout << "apwp3: " << apwp3 << endl;
delete apwp3;
AirplaneWithPool * apwp4 = new AirplaneWithPool();
cout << "apwp4: " << apwp4 << endl;
return 0;
}
The running results are as below.
//printed in the terminal
default // this means that sgi stl defines __default_alloc_template as the default allocator
apwp0: 0x804b008
apwp1: 0x804b010
apwp2: 0x804b018
apwp3: 0x804b010
apwp4: 0x804b010
If your STL library is not this version, copy those two files to your working directory and make some slight modifications to make sure that the compiler will find them. In fact, every STL library provides the header file "alloc.h", with some public interfaces to use, but __default_alloc_template, may not be defined. It is the "private" member of SGI STL.
Let us modify the data member of class AirplaneWithPool. AirplaneReq * req is replaced with char data[256]. Then the running results are below.
//printed in the terminal
default
apwp0: 0x804b008
apwp1: 0x804b110
apwp2: 0x804b218
apwp3: 0x804b110
apwp4: 0x804b110
This is the condition that the memory block request exceeds 128 bytes. So __malloc_alloc_allocator is used to deal with it, which means malloc() is called directly. But, I don't know why there is always an 8-byte extra block (0x804b110 - 0x804b008 = 0x0000108, and it is 256 + 8). Maybe it is used for bookkeeping or just aligning. What do you think?
The allocator we are going to use is __default_alloc_template, which deals with small block allocation. It will check the requested size first. If it exceeds some given size, in SGI STL which is 128 bytes, it will call __malloc_alloc_template to deal with it. Our wrapper here, MemoryPool, is also designed with template parameters, in order to be general for all the cases. The following code shows how it is implemented.
//MemoryPool.h
#ifndef _MEMORY_POOL_H
#define _MEMORY_POOL_H
#include <cstddef>
// make sure that stl_config.h, stl_alloc.h and alloc.h
// can be seen by the compiler, and it is better to
// put them in the user's current directory
#include "alloc.h"
template <typename T>
class MemoryPool ...{
public:
MemoryPool() : obj_size(sizeof(T)), block_size(16) ...{}
~MemoryPool() ...{}
void * Alloc(size_t);
void Free(void *, size_t);
public:
size_t obj_size, block_size;
};
template <typename T>
void * MemoryPool<T>::Alloc(size_t size) ...{
return __default_alloc_template<false, 0>::allocate(size);
}
template <typename T>
void MemoryPool<T>::Free(void * dead, size_t size) ...{
__default_alloc_template<false, 0>::deallocate(dead, size);
}
#endif
The classes AirplaneWithPool and AirplaneReq are still used here.
//AirplaneWithPool.h
#ifndef _AIRPLANE_WITH_POOL_H
#define _AIRPLANE_WITH_POOL_H
#include "MemoryPool.h"
#include <cstddef>
class AirplaneReq ...{
};
class AirplaneWithPool ...{
public:
static void * operator new(size_t);
static void operator delete(void *, size_t);
public:
AirplaneReq * req;
static MemoryPool<AirplaneWithPool> mem_pool;
};
#endif
//AirplaneWithPool.cpp
#include "AirplaneWithPool.h"
#include "MemoryPool.h"
MemoryPool<AirplaneWithPool> AirplaneWithPool::mem_pool;
void * AirplaneWithPool::operator new(size_t size) ...{
return mem_pool.Alloc(size);
}
void AirplaneWithPool::operator delete(void * dead_object, size_t size) ...{
mem_pool.Free(dead_object, size);
}
//item10WithPool.cpp
#include "AirplaneWithPool.h"
#include <iostream>
using namespace std;
int main() ...{
#ifdef __STL_USE_NAMESPACES
cout << "malloc" << endl;
#else
cout << "default" << endl;
#endif
AirplaneWithPool * apwp0 = new AirplaneWithPool();
cout << "apwp0: " << apwp0 << endl;
AirplaneWithPool * apwp1 = new AirplaneWithPool();
cout << "apwp1: " << apwp1 << endl;
AirplaneWithPool * apwp2 = new AirplaneWithPool();
cout << "apwp2: " << apwp2 << endl;
delete apwp1;
AirplaneWithPool * apwp3 = new AirplaneWithPool();
cout << "apwp3: " << apwp3 << endl;
delete apwp3;
AirplaneWithPool * apwp4 = new AirplaneWithPool();
cout << "apwp4: " << apwp4 << endl;
return 0;
}
The running results are as below.
//printed in the terminal
default // this means that sgi stl defines __default_alloc_template as the default allocator
apwp0: 0x804b008
apwp1: 0x804b010
apwp2: 0x804b018
apwp3: 0x804b010
apwp4: 0x804b010
If your STL library is not this version, copy those two files to your working directory and make some slight modifications to make sure that the compiler will find them. In fact, every STL library provides the header file "alloc.h", with some public interfaces to use, but __default_alloc_template, may not be defined. It is the "private" member of SGI STL.
Let us modify the data member of class AirplaneWithPool. AirplaneReq * req is replaced with char data[256]. Then the running results are below.
//printed in the terminal
default
apwp0: 0x804b008
apwp1: 0x804b110
apwp2: 0x804b218
apwp3: 0x804b110
apwp4: 0x804b110
This is the condition that the memory block request exceeds 128 bytes. So __malloc_alloc_allocator is used to deal with it, which means malloc() is called directly. But, I don't know why there is always an 8-byte extra block (0x804b110 - 0x804b008 = 0x0000108, and it is 256 + 8). Maybe it is used for bookkeeping or just aligning. What do you think?
相关文章推荐
- Implement memory allocator and deallocator using the mechanism in SGI STL
- Attempting to load the view of a view controller while it is deallocating is not allowed and may res
- SGI STL 源码解读之Allocator
- Structure of a C-Program in Memory | How Heap,Stack,Data and Code segments are stored in memory?
- STL:: allocator之deallocate & destory的区别与联系
- SGI STL 空间配置器(allocator)源码剖析
- angular4 JavaScript内存溢出问题 (FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory)
- Caused by: java.sql.SQLException: Out of memory; restart server and try again (needed 142328 bytes)
- Sample of STL(Vector):begin and rbegin
- The Usage of Lambda and Heap in the C++ STL
- SGI-STL学习笔记之allocator .
- Android bitmaps and out of memory errors
- A c++ class wrapper to simplify the use of CRITICAL_SECTION and avoid dead-lock
- A c++ class wrapper to simplify the use of CRITICAL_SECTION and avoid dead-lock
- 【STL】SGI空间配置器 Allocator
- Memory allocation and deallocation across dll boundaries
- Attempting to load the view of a view controller while it is deallocating is not allowed and may res
- My priliminary understanding of the relationship between virtual address and physical memory address
- Android Out of Memory Error: Causes, Solution and Best practices
- G. Of Zorcs and Axes----贪心+STL