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 
   32    extern const std::ptrdiff_t page_size;
 
   34    struct AllocationManager
 
   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 
  194    extern AllocationManager alloc_man;
 
  199  class DebugAllocator;
 
  203  class DebugAllocator<void> {
 
  205    typedef void* pointer;
 
  206    typedef const void* const_pointer;
 
  208    typedef void value_type;
 
  209    template <
class U> 
struct rebind {
 
  210      typedef DebugAllocator<U> other;
 
  234  class DebugAllocator {
 
  236    typedef std::size_t size_type;
 
  237    typedef std::ptrdiff_t difference_type;
 
  239    typedef const T* const_pointer;
 
  240    typedef T& reference;
 
  241    typedef const T& const_reference;
 
  242    typedef T value_type;
 
  243    template <
class U> 
struct rebind {
 
  244      typedef DebugAllocator<U> other;
 
  248    DebugAllocator() noexcept {}
 
  251    DebugAllocator(
const DebugAllocator<U>&) 
noexcept {}
 
  253    ~DebugAllocator() noexcept {}
 
  255    pointer address(reference x)
 const 
  259    const_pointer address(const_reference x)
 const 
  265    pointer allocate(size_type n,
 
  266                     [[maybe_unused]] DebugAllocator<void>::const_pointer hint = 0)
 
  268      return DebugMemory::alloc_man.allocate<T>(n);
 
  272    void deallocate(pointer p, size_type n)
 
  274      DebugMemory::alloc_man.deallocate<T>(p,n);
 
  278    size_type max_size() const noexcept
 
  280      return size_type(-1) / 
sizeof(T);
 
  284    void construct(pointer p, 
const T& val)
 
  286      ::new((
void*)p)T(val);
 
  290    template<
typename ... Args>
 
  291    void construct(pointer p, Args&&... args)
 
  293      ::new((
void *)p)T(std::forward<Args>(args) ...);
 
  297    void destroy(pointer p)
 
  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);
 
constexpr 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:238
 
constexpr 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:260
 
Allocators that use malloc/free.
 
Dune namespace.
Definition: alignedallocator.hh:13
 
constexpr std::integral_constant< std::size_t, sizeof...(II)> size(std::integer_sequence< T, II... >)
Return the size of the sequence.
Definition: integersequence.hh:75