5#ifndef DUNE_DEBUG_ALLOCATOR_HH
6#define DUNE_DEBUG_ALLOCATOR_HH
8#if __has_include(<sys/mman.h>)
11#define HAVE_SYS_MMAN_H 1
12#define HAVE_MPROTECT 1
36 typedef std::size_t size_type;
37 typedef std::ptrdiff_t difference_type;
38 typedef void* pointer;
41 static void allocation_error(
const char* msg);
43 struct AllocationInfo;
44 friend struct AllocationInfo;
46#define ALLOCATION_ASSERT(A) { if (!(A)) \
47 { allocation_error("Assertion " # A " failed");\
53 AllocationInfo(
const std::type_info & t) : type(&t) {}
54 const std::type_info * type;
64 typedef MallocAllocator<AllocationInfo> Alloc;
65 typedef std::vector<AllocationInfo, Alloc> AllocationList;
66 AllocationList allocation_list;
69 void memprotect([[maybe_unused]]
void* from,
70 [[maybe_unused]] difference_type len,
71 [[maybe_unused]]
int prot)
73#if HAVE_SYS_MMAN_H && HAVE_MPROTECT
74 int result = mprotect(from, len, prot);
78 std::cerr <<
"ERROR: (" << result <<
": " << strerror(result) <<
")" << std::endl;
79 std::cerr <<
" Failed to ";
80 if (prot == PROT_NONE)
81 std::cerr <<
"protect ";
83 std::cerr <<
"unprotect ";
84 std::cerr <<
"memory range: "
86 <<
static_cast<void*
>(
87 static_cast<char*
>(from) + len)
92 std::cerr <<
"WARNING: memory protection not available" << std::endl;
100 AllocationList::iterator it;
102 for (it=allocation_list.begin(); it!=allocation_list.end(); it++)
106 std::cerr <<
"ERROR: found memory chunk still in use: " <<
107 it->capacity <<
" bytes at " << it->ptr << std::endl;
110 munmap(it->page_ptr, it->pages * page_size);
113 allocation_error(
"lost allocations");
117 T* allocate(size_type n)
120 AllocationInfo ai(
typeid(T));
122 ai.capacity = n *
sizeof(T);
123 ai.pages = (ai.capacity) / page_size + 2;
125 size_type overlap = ai.capacity % page_size;
126 ai.page_ptr = mmap(NULL, ai.pages * page_size,
127 PROT_READ | PROT_WRITE,
129 MAP_ANON | MAP_PRIVATE,
131 MAP_ANONYMOUS | MAP_PRIVATE,
134 if (MAP_FAILED == ai.page_ptr)
136 throw std::bad_alloc();
138 ai.ptr =
static_cast<char*
>(ai.page_ptr) + page_size - overlap;
140 memprotect(
static_cast<char*
>(ai.page_ptr) + (ai.pages-1) * page_size,
144 allocation_list.push_back(ai);
146 return static_cast<T*
>(ai.ptr);
150 void deallocate(T* ptr, size_type n = 0) noexcept
155 (
char*)(ptr) - ((std::uintptr_t)(ptr) % page_size));
157 AllocationList::iterator it;
159 for (it=allocation_list.begin(); it!=allocation_list.end(); it++, i++)
161 if (it->page_ptr == page_ptr)
166 ALLOCATION_ASSERT(n == it->size);
167 ALLOCATION_ASSERT(ptr == it->ptr);
168 ALLOCATION_ASSERT(
true == it->not_free);
169 ALLOCATION_ASSERT(
typeid(T) == *(it->type));
171 it->not_free =
false;
172#if DEBUG_ALLOCATOR_KEEP
174 memprotect(it->page_ptr,
175 (it->pages) * page_size,
179 memprotect(it->page_ptr,
180 (it->pages) * page_size,
181 PROT_READ | PROT_WRITE);
182 munmap(it->page_ptr, it->pages * page_size);
184 allocation_list.erase(it);
189 allocation_error(
"memory block not found");
192#undef ALLOCATION_ASSERT
199 class DebugAllocator;
203 class DebugAllocator<void> {
209 template <
class U>
struct rebind {
210 typedef DebugAllocator<U> other;
234 class DebugAllocator {
243 template <
class U>
struct rebind {
244 typedef DebugAllocator<U> other;
268 return DebugMemory::alloc_man.allocate<T>(n);
274 DebugMemory::alloc_man.deallocate<T>(
p,n);
290 template<
typename ...
Args>
293 ::new((
void *)
p)T(std::forward<Args>(
args) ...);
306 operator==(
const DebugAllocator<T> &,
const DebugAllocator<T> &)
314 operator!=(
const DebugAllocator<T> &,
const DebugAllocator<T> &)
320#ifdef DEBUG_NEW_DELETE
321void *
operator new(
size_t size)
324 void *p = Dune::DebugMemory::alloc_man.allocate<
char>(size);
325#if DEBUG_NEW_DELETE > 2
326 std::cout <<
"NEW " << size
333void operator delete(
void * p)
noexcept
335#if DEBUG_NEW_DELETE > 2
336 std::cout <<
"FREE " << p << std::endl;
338 Dune::DebugMemory::alloc_man.deallocate<
char>(
static_cast<char*
>(p));
341void operator delete(
void * p,
size_t size)
noexcept
343#if DEBUG_NEW_DELETE > 2
344 std::cout <<
"FREE " << p << std::endl;
346 Dune::DebugMemory::alloc_man.deallocate<
char>(
static_cast<char*
>(p), size);
Allocators that use malloc/free.
ArrayList()
Constructs an Array list with one chunk.
Definition arraylist.hh:457
EnableIfInterOperable< T1, T2, bool >::type operator==(const ForwardIteratorFacade< T1, V1, R1, D > &lhs, const ForwardIteratorFacade< T2, V2, R2, D > &rhs)
Checks for equality.
Definition iteratorfacades.hh:237
EnableIfInterOperable< T1, T2, bool >::type operator!=(const ForwardIteratorFacade< T1, V1, R1, D > &lhs, const ForwardIteratorFacade< T2, V2, R2, D > &rhs)
Checks for inequality.
Definition iteratorfacades.hh:259
Dune namespace.
Definition alignedallocator.hh:13
T value_type
Value type for stl compliance.
Definition arraylist.hh:74
const T * const_pointer
The type of a const pointer to the type we store.
Definition arraylist.hh:94
const T & const_reference
The type of a const reference to the type we store.
Definition arraylist.hh:84
T & reference
The type of a reference to the type we store.
Definition arraylist.hh:79
std::size_t size_type
The size type.
Definition arraylist.hh:115
T * pointer
The type of a pointer to the type we store.
Definition arraylist.hh:89
std::ptrdiff_t difference_type
The difference type.
Definition arraylist.hh:120