Reputation: 23
I've been given a custom allocator that implements it's own allocation policies, its own malloc/free, etc. Now, I've been asked to use this custom allocator with a STL container (being it a vector or some other). I've created a class, say my_stdAllocator
, that is an interface compliant to the ISO C++ standard. through this class I call my allocator's methods. For example:
template <class T>
class my_stdAllocator {
// ...other required stuff...
// allocate 'num' elements of type T
pointer allocate(size_type num, const_pointer = 0) {
return static_cast<T*>(MYAllocator::instance()->malloc(num));
}
// deallocate memory at 'p'
void deallocate(pointer p, size_type num=0) {
MYAllocator::instance()->free(p);
}
// initialize allocated memory at 'p' with value 'value'
void construct(pointer p, const T& value) {
::new ((void*)p) T(value);
}
// destroy elements of initialized memory at p
void destroy(pointer p) {
p->~T();
}
// ...other required stuff...
} // end my_stdAllocator
The custom allocator normally works like a charm: it has been extensively tested, it definitely improves performances, limits fragmentation, etc. When I use it as the allocator for a stl container, (say, a vector) it has this weird behaviour in that it sometimes works properly, while it crashes with a segfault error some other times.
To give an example, it properly allocates and frees with a vector of char
:
typedef char TP;
int main(int argc, char* argv[]) {
std::vector<TP, my_stdAllocator<TP> > vec;
std::string s ("Whatever string, no matter how long...");
std::string::iterator it;
for (it=s.begin(); it<s.end(); ++it)
vec.push_back(*it);
...
It is ok when pushing "by hand" numbers inside the vector
typedef double TP;
int main(int argc, char* argv[]) {
std::vector<TP, my_stdAllocator<TP> > vec;
// "manual" push_back
vec.push_back(3.2);
vec.push_back(6.4);
vec.push_back(9.6);
vec.push_back(12.8);
vec.push_back(15.1);
vec.push_back(18.3);
vec.push_back(21.5);
...
It halts with a Segmentation fault when inserting elements through a loop:
typedef int TP;
int main(int argc, char* argv[]) {
std::vector<TP, ff_stdAllocatorInst<TP> > vec;
for(unsigned int i=0; i<size; ++i)
vec.push_back( (TP) i );
...
It works like a charm when reserving space for at least a certain number of elements:
typedef int TP;
int main(int argc, char* argv[]) {
std::vector<TP, ff_stdAllocatorInst<TP> > vec;
vec.reserve(size);
for(unsigned int i=0; i<size+150; ++i)
vec.push_back( (TP) i );
...
Notice that, the segfault mentioned above doesn't happen when using a placement new like this one:
void *p = MYAllocator::instance()->malloc(size);
std::vector<TP> *vec = new (p) std::vector<TP>
for(unsigned int i=0; i<size; ++i)
vec->push_back( (TP) i );
...
As I've said already, the custom allocator has been tested and works fine. My class is a simple interface between C++ standard and the custom allocator. I've tried to debug it wth gdb but it didn't help: the underlying allocator is ok, there must be some mistakes in my code but I cannot understand what is wrong!
Upvotes: 2
Views: 1562
Reputation: 4034
In your call to your custom allocator's malloc
function, you need to multiply by the size of the object you're allocating:
pointer allocate(size_type num, const_pointer = 0) {
return static_cast<T*>(MYAllocator::instance()->malloc(num*sizeof(T)));
}
Upvotes: 12