Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

malloc/free based STL allocator

Tags:

c++

stl

allocator

Is there a malloc/free based allocator in the STL? If not, does anyone know of a simple copy/paste one? I need it for a map that must not call new/delete.

like image 266
Baruch Avatar asked Jul 10 '12 14:07

Baruch


People also ask

Does std :: allocator use malloc?

Under the hood, the C function std::malloc will typically be used. Therefore, an allocator, who uses preallocated memory can gain a great performance boost. An adjusted allocator also makes a lot of sense, if you need a deterministic timing behavior of your program.

Can you malloc after free?

Occasionally, free can actually return memory to the operating system and make the process smaller. Usually, all it can do is allow a later call to malloc to reuse the space. In the meantime, the space remains in your program as part of a free-list used internally by malloc .

How does malloc find free space?

In C, the library function malloc is used to allocate a block of memory on the heap. The program accesses this block of memory via a pointer that malloc returns. When the memory is no longer needed, the pointer is passed to free which deallocates the memory so that it can be used for other purposes.

What does free malloc do?

One implementation of malloc/free does the following: Get a block of memory from the OS through sbrk() (Unix call). Create a header and a footer around that block of memory with some information such as size, permissions, and where the next and previous block are.


1 Answers

First, I'd note that changing the allocator for the map itself won't change the allocation used by the objects stored in the map. For example, if you do something like:

std::map<std::string, int, my_allocator<std::pair<const std::string, int> > m;

The map itself will allocate memory using the specified allocator, but when the std::strings in the map allocate memory, they'll still use the default allocator (which will use new and delete. So, if you need to avoid new and delete in general, you have to ensure that not only the map itself uses the right allocator, but that any objects it stores do the same (I know that's probably stating the obvious, but I've overlooked it, so maybe it's worth mentioning).

With that proviso, on with the code:

#ifndef ALLOCATOR_H_INC_
#define ALLOCATOR_H_INC_

#include <stdlib.h>
#include <new>
#include <limits>

namespace JVC {
template <class T> 
struct allocator {
    typedef size_t size_type;
    typedef ptrdiff_t difference_type;
    typedef T* pointer;
    typedef const T* const_pointer;
    typedef T& reference;
    typedef const T& const_reference;
    typedef T value_type;

    template <class U> struct rebind { typedef allocator<U> other; };
    allocator() throw() {}
    allocator(const allocator&) throw() {}

    template <class U> allocator(const allocator<U>&) throw(){}

    ~allocator() throw() {}

    pointer address(reference x) const { return &x; }
    const_pointer address(const_reference x) const { return &x; }

    pointer allocate(size_type s, void const * = 0) {
        if (0 == s)
            return NULL;
        pointer temp = (pointer)malloc(s * sizeof(T)); 
        if (temp == NULL)
            throw std::bad_alloc();
        return temp;
    }

    void deallocate(pointer p, size_type) {
        free(p);
    }

    size_type max_size() const throw() { 
        return std::numeric_limits<size_t>::max() / sizeof(T); 
    }

    void construct(pointer p, const T& val) {
        new((void *)p) T(val);
    }

    void destroy(pointer p) {
        p->~T();
    }
};
}

#endif

And, a little test code:

#include <map>
#include <vector>
#include <iostream>
#include <string>
#include <iterator>
#include "allocator.h"

// Technically this isn't allowed, but it's only demo code, so we'll live with it.
namespace std { 
std::ostream &operator<<(std::ostream &os, std::pair<std::string, int> const &c) { 
    return os << c.first << ": " << c.second;
}
}

int main() { 
    std::map<std::string, int, std::less<std::string>, 
             JVC::allocator<std::pair<const std::string, int> > > stuff;

    stuff["string 1"] = 1;
    stuff["string 2"] = 2;
    stuff["string 3"] = 3;

    std::copy(stuff.begin(), stuff.end(), 
        std::ostream_iterator<std::pair<std::string, int> >(std::cout, "\n"));

    return 0;
}
like image 121
Jerry Coffin Avatar answered Oct 19 '22 05:10

Jerry Coffin