WPILibC++ 2025.1.1
Loading...
Searching...
No Matches
debug_helpers.hpp
Go to the documentation of this file.
1// Copyright (C) 2015-2023 Jonathan Müller and foonathan/memory contributors
2// SPDX-License-Identifier: Zlib
3
4#ifndef WPI_MEMORY_DEBUG_HELPERS_HPP_INCLUDED
5#define WPI_MEMORY_DEBUG_HELPERS_HPP_INCLUDED
6
7#include <atomic>
8#include <type_traits>
9
10#include "../config.hpp"
11
12namespace wpi
13{
14 namespace memory
15 {
16 enum class debug_magic : unsigned char;
17 struct allocator_info;
18
19 namespace detail
20 {
21 using debug_fill_enabled = std::integral_constant<bool, WPI_MEMORY_DEBUG_FILL>;
22 constexpr std::size_t debug_fence_size =
24
25#if WPI_MEMORY_DEBUG_FILL
26 // fills size bytes of memory with debug_magic
27 void debug_fill(void* memory, std::size_t size, debug_magic m) noexcept;
28
29 // returns nullptr if memory is filled with debug_magic
30 // else returns pointer to mismatched byte
31 void* debug_is_filled(void* memory, std::size_t size, debug_magic m) noexcept;
32
33 // fills fence, new and fence
34 // returns after fence
35 void* debug_fill_new(void* memory, std::size_t node_size,
36 std::size_t fence_size = debug_fence_size) noexcept;
37
38 // fills free memory and returns memory starting at fence
39 void* debug_fill_free(void* memory, std::size_t node_size,
40 std::size_t fence_size = debug_fence_size) noexcept;
41
42 // fills internal memory
43 void debug_fill_internal(void* memory, std::size_t size, bool free) noexcept;
44#else
45 inline void debug_fill(void*, std::size_t, debug_magic) noexcept {}
46
47 inline void* debug_is_filled(void*, std::size_t, debug_magic) noexcept
48 {
49 return nullptr;
50 }
51
52 inline void* debug_fill_new(void* memory, std::size_t, std::size_t) noexcept
53 {
54 return memory;
55 }
56
57 inline void* debug_fill_free(void* memory, std::size_t, std::size_t) noexcept
58 {
59 return static_cast<char*>(memory);
60 }
61
62 inline void debug_fill_internal(void*, std::size_t, bool) noexcept {}
63#endif
64
66
67 // validates given ptr by evaluating the Functor
68 // if the Functor returns false, calls the debug_leak_checker
69 // note: ptr is just used as the information passed to the invalid ptr handler
70 template <class Functor>
71 void debug_check_pointer(Functor condition, const allocator_info& info, void* ptr)
72 {
73#if WPI_MEMORY_DEBUG_POINTER_CHECK
74 if (!condition())
76#else
77 (void)ptr;
78 (void)condition;
79 (void)info;
80#endif
81 }
82
83 // validates ptr by using a more expensive double-dealloc check
84 template <class Functor>
85 void debug_check_double_dealloc(Functor condition, const allocator_info& info,
86 void* ptr)
87 {
88#if WPI_MEMORY_DEBUG_DOUBLE_DEALLOC_CHECK
89 debug_check_pointer(condition, info, ptr);
90#else
91 (void)condition;
92 (void)info;
93 (void)ptr;
94#endif
95 }
96
97 void debug_handle_memory_leak(const allocator_info& info, std::ptrdiff_t amount);
98
99 // does no leak checking, null overhead
100 template <class Handler>
102 {
103 public:
104 no_leak_checker() noexcept {}
106 ~no_leak_checker() noexcept {}
107
109 {
110 return *this;
111 }
112
113 void on_allocate(std::size_t) noexcept {}
114 void on_deallocate(std::size_t) noexcept {}
115 };
116
117 // does leak checking per-object
118 // leak is detected upon destructor
119 template <class Handler>
120 class object_leak_checker : Handler
121 {
122 public:
123 object_leak_checker() noexcept : allocated_(0) {}
124
126 : allocated_(other.allocated_)
127 {
128 other.allocated_ = 0;
129 }
130
132 {
133 if (allocated_ != 0)
134 this->operator()(allocated_);
135 }
136
138 {
139 allocated_ = other.allocated_;
140 other.allocated_ = 0;
141 return *this;
142 }
143
144 void on_allocate(std::size_t size) noexcept
145 {
146 allocated_ += std::ptrdiff_t(size);
147 }
148
149 void on_deallocate(std::size_t size) noexcept
150 {
151 allocated_ -= std::ptrdiff_t(size);
152 }
153
154 private:
155 std::ptrdiff_t allocated_;
156 };
157
158 // does leak checking on a global basis
159 // call macro WPI_MEMORY_GLOBAL_LEAK_CHECKER(handler, var_name) in the header
160 // when last counter gets destroyed, leak is detected
161 template <class Handler>
163 {
164 public:
165 struct counter : Handler
166 {
168 {
169 ++no_counter_objects_;
170 }
171
173 {
174 --no_counter_objects_;
175 if (no_counter_objects_ == 0u && allocated_ != 0u)
176 this->operator()(allocated_);
177 }
178 };
179
183
185 {
186 return *this;
187 }
188
189 void on_allocate(std::size_t size) noexcept
190 {
191 allocated_ += std::ptrdiff_t(size);
192 }
193
194 void on_deallocate(std::size_t size) noexcept
195 {
196 allocated_ -= std::ptrdiff_t(size);
197 }
198
199 private:
200 static std::atomic<std::size_t> no_counter_objects_;
201 static std::atomic<std::ptrdiff_t> allocated_;
202 };
203
204 template <class Handler>
205 std::atomic<std::size_t> global_leak_checker_impl<Handler>::no_counter_objects_(0u);
206
207 template <class Handler>
208 std::atomic<std::ptrdiff_t> global_leak_checker_impl<Handler>::allocated_(0);
209
210#if WPI_MEMORY_DEBUG_LEAK_CHECK
211 template <class Handler>
212 using global_leak_checker = global_leak_checker_impl<Handler>;
213
214#define WPI_MEMORY_GLOBAL_LEAK_CHECKER(handler, var_name) \
215 static wpi::memory::detail::global_leak_checker<handler>::counter var_name;
216#else
217 template <class Handler>
218 using global_leak_checker = no_leak_checker<int>; // only one instantiation
219
220#define WPI_MEMORY_GLOBAL_LEAK_CHECKER(handler, var_name)
221#endif
222
223#if WPI_MEMORY_DEBUG_LEAK_CHECK
224 template <class Handler>
225 using default_leak_checker = object_leak_checker<Handler>;
226#else
227 template <class Handler>
229#endif
230 } // namespace detail
231 } // namespace memory
232} // namespace wpi
233
234#endif // WPI_MEMORY_DEBUG_HELPERS_HPP_INCLUDED
and restrictions which apply to each piece of software is included later in this file and or inside of the individual applicable source files The disclaimer of warranty in the WPILib license above applies to all code in and nothing in any of the other licenses gives permission to use the names of FIRST nor the names of the WPILib contributors to endorse or promote products derived from this software The following pieces of software have additional or alternate and or and nanopb were all modified for use in Google Inc All rights reserved Redistribution and use in source and binary with or without are permitted provided that the following conditions are this list of conditions and the following disclaimer *Redistributions in binary form must reproduce the above copyright this list of conditions and the following disclaimer in the documentation and or other materials provided with the distribution *Neither the name of Google Inc nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY EXPRESS OR IMPLIED BUT NOT LIMITED THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY OR CONSEQUENTIAL WHETHER IN STRICT OR EVEN IF ADVISED OF THE POSSIBILITY OF SUCH January AND DISTRIBUTION Definitions License shall mean the terms and conditions for and distribution as defined by Sections through of this document Licensor shall mean the copyright owner or entity authorized by the copyright owner that is granting the License Legal Entity shall mean the union of the acting entity and all other entities that control are controlled by or are under common control with that entity For the purposes of this definition control direct or to cause the direction or management of such whether by contract or including but not limited to software source documentation and configuration files Object form shall mean any form resulting from mechanical transformation or translation of a Source including but not limited to compiled object generated and conversions to other media types Work shall mean the work of whether in Source or Object made available under the as indicated by a copyright notice that is included in or attached to the whether in Source or Object that is based or other modifications as a an original work of authorship For the purposes of this Derivative Works shall not include works that remain separable or merely the Work and Derivative Works thereof Contribution shall mean any work of including the original version of the Work and any modifications or additions to that Work or Derivative Works that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner For the purposes of this submitted means any form of or written communication sent to the Licensor or its including but not limited to communication on electronic mailing source code control and issue tracking systems that are managed or on behalf the Licensor for the purpose of discussing and improving the but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as Not a Contribution Contributor shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work Grant of Copyright License Subject to the terms and conditions of this each Contributor hereby grants to You a non no royalty free
Definition ThirdPartyNotices.txt:164
Definition debug_helpers.hpp:163
global_leak_checker_impl() noexcept
Definition debug_helpers.hpp:180
global_leak_checker_impl & operator=(global_leak_checker_impl &&) noexcept
Definition debug_helpers.hpp:184
global_leak_checker_impl(global_leak_checker_impl &&) noexcept
Definition debug_helpers.hpp:181
void on_deallocate(std::size_t size) noexcept
Definition debug_helpers.hpp:194
~global_leak_checker_impl() noexcept
Definition debug_helpers.hpp:182
void on_allocate(std::size_t size) noexcept
Definition debug_helpers.hpp:189
Definition debug_helpers.hpp:102
no_leak_checker(no_leak_checker &&) noexcept
Definition debug_helpers.hpp:105
void on_allocate(std::size_t) noexcept
Definition debug_helpers.hpp:113
~no_leak_checker() noexcept
Definition debug_helpers.hpp:106
no_leak_checker & operator=(no_leak_checker &&) noexcept
Definition debug_helpers.hpp:108
void on_deallocate(std::size_t) noexcept
Definition debug_helpers.hpp:114
no_leak_checker() noexcept
Definition debug_helpers.hpp:104
Definition debug_helpers.hpp:121
void on_allocate(std::size_t size) noexcept
Definition debug_helpers.hpp:144
object_leak_checker & operator=(object_leak_checker &&other) noexcept
Definition debug_helpers.hpp:137
object_leak_checker(object_leak_checker &&other) noexcept
Definition debug_helpers.hpp:125
void on_deallocate(std::size_t size) noexcept
Definition debug_helpers.hpp:149
object_leak_checker() noexcept
Definition debug_helpers.hpp:123
~object_leak_checker() noexcept
Definition debug_helpers.hpp:131
Configuration macros.
auto ptr(T p) -> const void *
Converts p to const void* for pointer formatting.
Definition format.h:3821
#define WPI_MEMORY_DEBUG_FENCE
The size of the fence memory, it has no effect if WPI_MEMORY_DEBUG_FILL is false.
Definition config.hpp:114
#define WPI_MEMORY_DEBUG_FILL
Whether or not allocated memory will be filled with special values.
Definition config.hpp:109
debug_magic
The magic values that are used for debug filling.
Definition debugging.hpp:23
detail namespace with internal helper functions
Definition input_adapters.h:32
std::integral_constant< bool, WPI_MEMORY_DEBUG_FILL > debug_fill_enabled
Definition debug_helpers.hpp:21
no_leak_checker< int > global_leak_checker
Definition debug_helpers.hpp:218
void debug_check_double_dealloc(Functor condition, const allocator_info &info, void *ptr)
Definition debug_helpers.hpp:85
void * debug_fill_new(void *memory, std::size_t, std::size_t) noexcept
Definition debug_helpers.hpp:52
void debug_fill(void *, std::size_t, debug_magic) noexcept
Definition debug_helpers.hpp:45
void * debug_fill_free(void *memory, std::size_t, std::size_t) noexcept
Definition debug_helpers.hpp:57
void debug_handle_memory_leak(const allocator_info &info, std::ptrdiff_t amount)
constexpr std::size_t debug_fence_size
Definition debug_helpers.hpp:22
void * debug_is_filled(void *, std::size_t, debug_magic) noexcept
Definition debug_helpers.hpp:47
void debug_handle_invalid_ptr(const allocator_info &info, void *ptr)
void debug_check_pointer(Functor condition, const allocator_info &info, void *ptr)
Definition debug_helpers.hpp:71
void debug_fill_internal(void *, std::size_t, bool) noexcept
Definition debug_helpers.hpp:62
no_leak_checker< Handler > default_leak_checker
Definition debug_helpers.hpp:228
Memory namespace.
Definition heap_allocator.hpp:20
Foonathan namespace.
Definition ntcore_cpp.h:26
Contains information about an allocator.
Definition error.hpp:23