3#ifndef DUNE_DEBUG_ALLOCATOR_HH
4#define DUNE_DEBUG_ALLOCATOR_HH
14#if HAVE_SYS_MMAN_H and HAVE_MPROTECT
17enum DummyProtFlags { PROT_NONE, PROT_WRITE, PROT_READ };
29 extern const std::ptrdiff_t page_size;
31 struct AllocationManager
33 typedef std::size_t size_type;
34 typedef std::ptrdiff_t difference_type;
35 typedef void* pointer;
38 static void allocation_error(
const char* msg);
40 struct AllocationInfo;
41 friend struct AllocationInfo;
43#define ALLOCATION_ASSERT(A) { if (!(A)) \
44 { allocation_error("Assertion " # A " failed");\
50 AllocationInfo(
const std::type_info & t) : type(&t) {}
51 const std::type_info * type;
61 typedef MallocAllocator<AllocationInfo> Alloc;
62 typedef std::vector<AllocationInfo, Alloc> AllocationList;
63 AllocationList allocation_list;
66 void memprotect(
void* from, difference_type len,
int prot)
68#if HAVE_SYS_MMAN_H and HAVE_MPROTECT
69 int result = mprotect(from, len, prot);
73 std::cerr <<
"ERROR: (" << result <<
": " << strerror(result) <<
")" << std::endl;
74 std::cerr <<
" Failed to ";
75 if (prot == PROT_NONE)
76 std::cerr <<
"protect ";
78 std::cerr <<
"unprotect ";
79 std::cerr <<
"memory range: "
81 <<
static_cast<void*
>(
82 static_cast<char*
>(from) + len)
90 std::cerr <<
"WARNING: memory protection not available" << std::endl;
98 AllocationList::iterator it;
100 for (it=allocation_list.begin(); it!=allocation_list.end(); it++)
104 std::cerr <<
"ERROR: found memory chunk still in use: " <<
105 it->capacity <<
" bytes at " << it->ptr << std::endl;
111 allocation_error(
"lost allocations");
115 T* allocate(size_type n)
throw(std::bad_alloc)
118 AllocationInfo ai(
typeid(T));
120 ai.capacity = n *
sizeof(T);
121 ai.pages = (ai.capacity) / page_size + 2;
123 size_type overlap = ai.capacity % page_size;
124 int result = posix_memalign(&(ai.page_ptr), page_size, ai.pages * page_size);
127 throw std::bad_alloc();
129 ai.ptr =
static_cast<char*
>(ai.page_ptr) + page_size - overlap;
131 memprotect(
static_cast<char*
>(ai.page_ptr) + (ai.pages-1) * page_size,
135 allocation_list.push_back(ai);
137 return static_cast<T*
>(ai.ptr);
141 void deallocate(T* ptr, size_type n = 0) throw()
146 (
char*)(ptr) - ((difference_type)(ptr) % page_size));
148 AllocationList::iterator it;
150 for (it=allocation_list.begin(); it!=allocation_list.end(); it++, i++)
152 if (it->page_ptr == page_ptr)
157 ALLOCATION_ASSERT(n == it->size);
158 ALLOCATION_ASSERT(ptr == it->ptr);
159 ALLOCATION_ASSERT(
true == it->not_free);
160 ALLOCATION_ASSERT(
typeid(T) == *(it->type));
162 it->not_free =
false;
163#if DEBUG_ALLOCATOR_KEEP
165 memprotect(it->page_ptr,
166 (it->pages) * page_size,
170 memprotect(it->page_ptr,
171 (it->pages) * page_size,
172 PROT_READ | PROT_WRITE);
173 std::free(it->page_ptr);
175 allocation_list.erase(it);
180 allocation_error(
"memory block not found");
183#undef ALLOCATION_ASSERT
185 extern AllocationManager alloc_man;
190 class DebugAllocator;
194 class DebugAllocator<void> {
196 typedef void* pointer;
197 typedef const void* const_pointer;
199 typedef void value_type;
200 template <
class U>
struct rebind {
201 typedef DebugAllocator<U> other;
227 typedef std::size_t size_type;
228 typedef std::ptrdiff_t difference_type;
230 typedef const T* const_pointer;
231 typedef T& reference;
232 typedef const T& const_reference;
233 typedef T value_type;
234 template <
class U>
struct rebind {
246 pointer address(reference x)
const
250 const_pointer address(const_reference x)
const
257 DebugAllocator<void>::const_pointer hint = 0)
260 return DebugMemory::alloc_man.allocate<T>(n);
266 DebugMemory::alloc_man.deallocate<T>(p,n);
272 return size_type(-1) /
sizeof(T);
278 ::new((
void*)p)T(val);
280#if ( HAVE_VARIADIC_TEMPLATES && HAVE_RVALUE_REFERENCES ) || DOXYGEN
283 template<
typename ... _Args>
286 ::new((
void *)p)T(std::forward<_Args>(__args) ...);
297#ifdef DEBUG_NEW_DELETE
298void *
operator new(
size_t size)
throw(std::bad_alloc)
301 void *p = Dune::DebugMemory::alloc_man.allocate<
char>(size);
302#if DEBUG_NEW_DELETE > 2
303 std::cout <<
"NEW " << size
310void operator delete(
void * p)
throw()
312#if DEBUG_NEW_DELETE > 2
313 std::cout <<
"FREE " << p << std::endl;
315 Dune::DebugMemory::alloc_man.deallocate<
char>(
static_cast<char*
>(p));
Allocators implementation which performs different kind of memory checks.
Definition: debugallocator.hh:225
void destroy(pointer p)
destroy an object of type T (i.e. call the destructor)
Definition: debugallocator.hh:290
~DebugAllocator()
cleanup this allocator
Definition: debugallocator.hh:244
size_type max_size() const
max size for allocate
Definition: debugallocator.hh:270
void deallocate(pointer p, size_type n)
deallocate n objects of type T at address p
Definition: debugallocator.hh:264
DebugAllocator(const DebugAllocator< U > &)
copy construct from an other DebugAllocator, possibly for a different result type
Definition: debugallocator.hh:242
void construct(pointer p, _Args &&... __args)
Definition: debugallocator.hh:284
void construct(pointer p, const T &val)
copy-construct an object of type T (i.e. make a placement new on p)
Definition: debugallocator.hh:276
DebugAllocator()
create a new DebugAllocator
Definition: debugallocator.hh:239
pointer allocate(size_type n, DebugAllocator< void >::const_pointer hint=0)
allocate n objects of type T
Definition: debugallocator.hh:256
Allocators that use malloc/free.
Dune namespace.
Definition: alignment.hh:14
Definition of the DUNE_UNUSED macro for the case that config.h is not available.
#define DUNE_UNUSED_PARAMETER(parm)
A macro to mark intentional unused function parameters with.
Definition: unused.hh:18