libstdc++
debug_allocator.h
Go to the documentation of this file.
1// Allocators -*- C++ -*-
2
3// Copyright (C) 2001-2022 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/*
26 * Copyright (c) 1996-1997
27 * Silicon Graphics Computer Systems, Inc.
28 *
29 * Permission to use, copy, modify, distribute and sell this software
30 * and its documentation for any purpose is hereby granted without fee,
31 * provided that the above copyright notice appear in all copies and
32 * that both that copyright notice and this permission notice appear
33 * in supporting documentation. Silicon Graphics makes no
34 * representations about the suitability of this software for any
35 * purpose. It is provided "as is" without express or implied warranty.
36 */
37
38/** @file ext/debug_allocator.h
39 * This file is a GNU extension to the Standard C++ Library.
40 */
41
42#ifndef _DEBUG_ALLOCATOR_H
43#define _DEBUG_ALLOCATOR_H 1
44
45#include <stdexcept>
46#include <bits/functexcept.h>
47#include <ext/alloc_traits.h>
48
49namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
50{
51_GLIBCXX_BEGIN_NAMESPACE_VERSION
52
53 /**
54 * @brief A meta-allocator with debugging bits.
55 * @ingroup allocators
56 *
57 * This is precisely the allocator defined in the C++03 Standard.
58 */
59 template<typename _Alloc>
61 {
62 template<typename> friend class debug_allocator;
63
65
66 public:
67 typedef typename _Traits::size_type size_type;
68 typedef typename _Traits::difference_type difference_type;
69 typedef typename _Traits::pointer pointer;
70 typedef typename _Traits::const_pointer const_pointer;
71 typedef typename _Traits::reference reference;
72 typedef typename _Traits::const_reference const_reference;
73 typedef typename _Traits::value_type value_type;
74
75 template<typename _Up>
76 class rebind
77 {
78 typedef typename _Traits::template rebind<_Up>::other __other;
79
80 public:
81 typedef debug_allocator<__other> other;
82 };
83
84 private:
85 // _M_extra is the number of objects that correspond to the
86 // extra space where debug information is stored.
87 size_type _M_extra;
88
89 _Alloc _M_allocator;
90
91 template<typename _Alloc2,
92 typename = typename __alloc_traits<_Alloc2>::template
94 struct __convertible
95 { };
96
97 template<typename _Alloc2>
98 struct __convertible<_Alloc2, _Alloc>
99 {
100 typedef void* __type;
101 };
102
103 size_type _S_extra()
104 {
105 const std::size_t __obj_size = sizeof(value_type);
106 return (sizeof(size_type) + __obj_size - 1) / __obj_size;
107 }
108
109 public:
110 debug_allocator() : _M_extra(_S_extra()) { }
111
112 template<typename _Alloc2>
114 typename __convertible<_Alloc2>::__type = 0)
115 : _M_extra(_S_extra()), _M_allocator(__a2._M_allocator) { }
116
117 debug_allocator(const _Alloc& __a)
118 : _M_extra(_S_extra()), _M_allocator(__a) { }
119
120 _GLIBCXX_NODISCARD pointer
121 allocate(size_type __n)
122 {
123 pointer __res = _M_allocator.allocate(__n + _M_extra);
124 size_type* __ps = reinterpret_cast<size_type*>(__res);
125 *__ps = __n;
126 return __res + _M_extra;
127 }
128
129 _GLIBCXX_NODISCARD pointer
130 allocate(size_type __n, const void* __hint)
131 {
132 pointer __res = _M_allocator.allocate(__n + _M_extra, __hint);
133 size_type* __ps = reinterpret_cast<size_type*>(__res);
134 *__ps = __n;
135 return __res + _M_extra;
136 }
137
138 void
139 deallocate(pointer __p, size_type __n)
140 {
141 using std::__throw_runtime_error;
142 if (__p)
143 {
144 pointer __real_p = __p - _M_extra;
145 if (*reinterpret_cast<size_type*>(__real_p) != __n)
146 __throw_runtime_error("debug_allocator::deallocate wrong size");
147 _M_allocator.deallocate(__real_p, __n + _M_extra);
148 }
149 else
150 __throw_runtime_error("debug_allocator::deallocate null pointer");
151 }
152
153 void
154 construct(pointer __p, const value_type& __val)
155 { _Traits::construct(_M_allocator, __p, __val); }
156
157#if __cplusplus >= 201103L
158 template<typename _Tp, typename... _Args>
159 void
160 construct(_Tp* __p, _Args&&... __args)
161 {
162 _Traits::construct(_M_allocator, __p,
163 std::forward<_Args>(__args)...);
164 }
165#endif
166
167 template<typename _Tp>
168 void
169 destroy(_Tp* __p)
170 { _Traits::destroy(_M_allocator, __p); }
171
172 size_type
173 max_size() const throw()
174 { return _Traits::max_size(_M_allocator) - _M_extra; }
175
176 template<typename _Alloc2>
177 friend bool
178 operator==(const debug_allocator& __lhs,
179 const debug_allocator<_Alloc2>& __rhs) _GLIBCXX_NOTHROW
180 { return __lhs._M_allocator == debug_allocator(__rhs)._M_allocator; }
181
182#if __cpp_impl_three_way_comparison < 201907L
183 template<typename _Alloc2>
184 friend bool
185 operator!=(const debug_allocator& __lhs,
186 const debug_allocator<_Alloc2>& __rhs) _GLIBCXX_NOTHROW
187 { return !(__lhs == __rhs); }
188#endif
189 };
190
191_GLIBCXX_END_NAMESPACE_VERSION
192} // namespace
193
194#endif
GNU extensions for public use.
Uniform interface to C++98 and C++11 allocators.
static constexpr size_type max_size(const _Alloc &__a) noexcept
The maximum supported allocation size.
A meta-allocator with debugging bits.