Sat, 16 Apr 2022 20:17:01 +0200
improve testing allocator + add tests for it
test/CMakeLists.txt | file | annotate | diff | comparison | revisions | |
test/test_list.cpp | file | annotate | diff | comparison | revisions | |
test/util_allocator.c | file | annotate | diff | comparison | revisions | |
test/util_allocator.cpp | file | annotate | diff | comparison | revisions | |
test/util_allocator.h | file | annotate | diff | comparison | revisions |
1.1 --- a/test/CMakeLists.txt Sat Apr 16 18:02:10 2022 +0200 1.2 +++ b/test/CMakeLists.txt Sat Apr 16 20:17:01 2022 +0200 1.3 @@ -18,7 +18,7 @@ 1.4 test_list.cpp 1.5 test_tree.cpp 1.6 selftest.cpp 1.7 - util_allocator.c 1.8 + util_allocator.cpp 1.9 ) 1.10 target_link_libraries(ucxtest PRIVATE ucx_static gtest_main) 1.11 gtest_discover_tests(ucxtest)
2.1 --- a/test/test_list.cpp Sat Apr 16 18:02:10 2022 +0200 2.2 +++ b/test/test_list.cpp Sat Apr 16 20:17:01 2022 +0200 2.3 @@ -552,13 +552,11 @@ 2.4 class HighLevelTest : public ::testing::Test { 2.5 mutable std::unordered_set<CxList *> lists; 2.6 protected: 2.7 - void SetUp() override { 2.8 - cxTestingAllocatorReset(); 2.9 - } 2.10 + CxTestingAllocator testingAllocator; 2.11 2.12 void TearDown() override { 2.13 for (auto &&l: lists) cxListDestroy(l); 2.14 - EXPECT_TRUE(cxTestingAllocatorVerify()); 2.15 + EXPECT_TRUE(testingAllocator.verify()); 2.16 } 2.17 2.18 static constexpr size_t testdata_len = 250; 2.19 @@ -572,7 +570,7 @@ 2.20 auto linkedListFromTestData() const -> CxList * { 2.21 return autofree( 2.22 cxLinkedListFromArray( 2.23 - cxTestingAllocator, 2.24 + &testingAllocator, 2.25 cmp_int, 2.26 sizeof(int), 2.27 testdata_len, 2.28 @@ -582,15 +580,15 @@ 2.29 } 2.30 2.31 auto pointerLinkedListFromTestData() const -> CxList * { 2.32 - auto list = autofree(cxPointerLinkedListCreate(cxTestingAllocator, cmp_int)); 2.33 + auto list = autofree(cxPointerLinkedListCreate(&testingAllocator, cmp_int)); 2.34 cx_for_n(i, testdata_len) cxListAdd(list, &testdata.data[i]); 2.35 return list; 2.36 } 2.37 2.38 - static void verifyCreate(CxList *list) { 2.39 + void verifyCreate(CxList *list) const { 2.40 EXPECT_EQ(list->size, 0); 2.41 EXPECT_EQ(list->capacity, (size_t) -1); 2.42 - EXPECT_EQ(list->allocator, cxTestingAllocator); 2.43 + EXPECT_EQ(list->allocator, &testingAllocator); 2.44 EXPECT_EQ(list->cmpfunc, cmp_int); 2.45 } 2.46 2.47 @@ -736,41 +734,41 @@ 2.48 }; 2.49 2.50 TEST_F(LinkedList, cxLinkedListCreate) { 2.51 - CxList *list = autofree(cxLinkedListCreate(cxTestingAllocator, cmp_int, sizeof(int))); 2.52 + CxList *list = autofree(cxLinkedListCreate(&testingAllocator, cmp_int, sizeof(int))); 2.53 EXPECT_EQ(list->itemsize, sizeof(int)); 2.54 verifyCreate(list); 2.55 } 2.56 2.57 TEST_F(PointerLinkedList, cxPointerLinkedListCreate) { 2.58 - CxList *list = autofree(cxPointerLinkedListCreate(cxTestingAllocator, cmp_int)); 2.59 + CxList *list = autofree(cxPointerLinkedListCreate(&testingAllocator, cmp_int)); 2.60 EXPECT_EQ(list->itemsize, sizeof(void *)); 2.61 verifyCreate(list); 2.62 } 2.63 2.64 TEST_F(LinkedList, cxLinkedListFromArray) { 2.65 - CxList *expected = autofree(cxLinkedListCreate(cxTestingAllocator, cmp_int, sizeof(int))); 2.66 + CxList *expected = autofree(cxLinkedListCreate(&testingAllocator, cmp_int, sizeof(int))); 2.67 cx_for_n (i, testdata_len) cxListAdd(expected, &testdata.data[i]); 2.68 - CxList *list = autofree(cxLinkedListFromArray(cxTestingAllocator, cmp_int, sizeof(int), 2.69 + CxList *list = autofree(cxLinkedListFromArray(&testingAllocator, cmp_int, sizeof(int), 2.70 testdata_len, testdata.data.data())); 2.71 EXPECT_EQ(cxListCompare(list, expected), 0); 2.72 } 2.73 2.74 TEST_F(LinkedList, cxListAdd) { 2.75 - CxList *list = autofree(cxLinkedListCreate(cxTestingAllocator, cmp_int, sizeof(int))); 2.76 + CxList *list = autofree(cxLinkedListCreate(&testingAllocator, cmp_int, sizeof(int))); 2.77 verifyAdd(list, false); 2.78 } 2.79 2.80 TEST_F(PointerLinkedList, cxListAdd) { 2.81 - CxList *list = autofree(cxPointerLinkedListCreate(cxTestingAllocator, cmp_int)); 2.82 + CxList *list = autofree(cxPointerLinkedListCreate(&testingAllocator, cmp_int)); 2.83 verifyAdd(list, true); 2.84 } 2.85 2.86 TEST_F(LinkedList, cxListInsert) { 2.87 - verifyInsert(autofree(cxLinkedListCreate(cxTestingAllocator, cmp_int, sizeof(int)))); 2.88 + verifyInsert(autofree(cxLinkedListCreate(&testingAllocator, cmp_int, sizeof(int)))); 2.89 } 2.90 2.91 TEST_F(PointerLinkedList, cxListInsert) { 2.92 - verifyInsert(autofree(cxPointerLinkedListCreate(cxTestingAllocator, cmp_int))); 2.93 + verifyInsert(autofree(cxPointerLinkedListCreate(&testingAllocator, cmp_int))); 2.94 } 2.95 2.96 TEST_F(LinkedList, cxListRemove) { 2.97 @@ -815,13 +813,13 @@ 2.98 2.99 TEST_F(LinkedList, InsertViaIterator) { 2.100 int fivenums[] = {0, 1, 2, 3, 4, 5}; 2.101 - CxList *list = autofree(cxLinkedListFromArray(cxTestingAllocator, cmp_int, sizeof(int), 5, fivenums)); 2.102 + CxList *list = autofree(cxLinkedListFromArray(&testingAllocator, cmp_int, sizeof(int), 5, fivenums)); 2.103 verifyInsertViaIterator(list); 2.104 } 2.105 2.106 TEST_F(PointerLinkedList, InsertViaIterator) { 2.107 int fivenums[] = {0, 1, 2, 3, 4, 5}; 2.108 - CxList *list = autofree(cxPointerLinkedListCreate(cxTestingAllocator, cmp_int)); 2.109 + CxList *list = autofree(cxPointerLinkedListCreate(&testingAllocator, cmp_int)); 2.110 cx_for_n (i, 5) cxListAdd(list, &fivenums[i]); 2.111 verifyInsertViaIterator(list); 2.112 }
3.1 --- a/test/util_allocator.c Sat Apr 16 18:02:10 2022 +0200 3.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 3.3 @@ -1,126 +0,0 @@ 3.4 -/* 3.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3.6 - * 3.7 - * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 3.8 - * 3.9 - * Redistribution and use in source and binary forms, with or without 3.10 - * modification, are permitted provided that the following conditions are met: 3.11 - * 3.12 - * 1. Redistributions of source code must retain the above copyright 3.13 - * notice, this list of conditions and the following disclaimer. 3.14 - * 3.15 - * 2. Redistributions in binary form must reproduce the above copyright 3.16 - * notice, this list of conditions and the following disclaimer in the 3.17 - * documentation and/or other materials provided with the distribution. 3.18 - * 3.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 3.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 3.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 3.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 3.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 3.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 3.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 3.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 3.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3.29 - * POSSIBILITY OF SUCH DAMAGE. 3.30 - */ 3.31 - 3.32 -#include "util_allocator.h" 3.33 -#include <string.h> 3.34 - 3.35 -void cx_testing_allocator_add(cx_testing_allocator_s *data, void *ptr) { 3.36 - data->tracked[data->live] = ptr; 3.37 - data->live++; 3.38 -} 3.39 - 3.40 -int cx_testing_allocator_remove(cx_testing_allocator_s *data, void *ptr) { 3.41 - for (int i = 0; i < data->live; i++) { 3.42 - if (data->tracked[i] == ptr) { 3.43 - data->tracked[i] = data->tracked[data->live - 1]; 3.44 - data->live--; 3.45 - return 0; 3.46 - } 3.47 - } 3.48 - return 1; 3.49 -} 3.50 - 3.51 -void *cx_malloc_testing(void *d, size_t n) { 3.52 - cx_testing_allocator_s *data = d; 3.53 - void *ptr = malloc(n); 3.54 - data->alloc_total++; 3.55 - if (ptr == NULL) { 3.56 - data->alloc_failed++; 3.57 - } else { 3.58 - cx_testing_allocator_add(data, ptr); 3.59 - } 3.60 - return ptr; 3.61 -} 3.62 - 3.63 -void *cx_realloc_testing(void *d, void *mem, size_t n) { 3.64 - cx_testing_allocator_s *data = d; 3.65 - void *ptr = realloc(mem, n); 3.66 - if (ptr == mem) { 3.67 - return ptr; 3.68 - } else { 3.69 - data->alloc_total++; 3.70 - if (ptr == NULL) { 3.71 - data->alloc_failed++; 3.72 - } else { 3.73 - data->free_total++; 3.74 - if (cx_testing_allocator_remove(data, mem)) { 3.75 - data->free_failed++; 3.76 - } 3.77 - cx_testing_allocator_add(data, ptr); 3.78 - } 3.79 - return ptr; 3.80 - } 3.81 -} 3.82 - 3.83 -void *cx_calloc_testing(void *d, size_t nelem, size_t n) { 3.84 - cx_testing_allocator_s *data = d; 3.85 - void *ptr = calloc(nelem, n); 3.86 - data->alloc_total++; 3.87 - if (ptr == NULL) { 3.88 - data->alloc_failed++; 3.89 - } else { 3.90 - cx_testing_allocator_add(data, ptr); 3.91 - } 3.92 - return ptr; 3.93 -} 3.94 - 3.95 -void cx_free_testing(void *d, void *mem) { 3.96 - cx_testing_allocator_s *data = d; 3.97 - data->free_total++; 3.98 - if (cx_testing_allocator_remove(data, mem)) { 3.99 - data->free_failed++; 3.100 - // do not even attempt to free mem, because it is likely to segfault 3.101 - } else { 3.102 - free(mem); 3.103 - } 3.104 -} 3.105 - 3.106 -cx_allocator_class cx_testing_allocator_class = { 3.107 - cx_malloc_testing, 3.108 - cx_realloc_testing, 3.109 - cx_calloc_testing, 3.110 - cx_free_testing 3.111 -}; 3.112 - 3.113 -cx_testing_allocator_s cx_testing_allocator_data; 3.114 - 3.115 -struct cx_allocator_s cx_testing_allocator = { 3.116 - &cx_testing_allocator_class, 3.117 - &cx_testing_allocator_data 3.118 -}; 3.119 -CxAllocator *cxTestingAllocator = &cx_testing_allocator; 3.120 - 3.121 -void cxTestingAllocatorReset(void) { 3.122 - memset(&cx_testing_allocator_data, 0, sizeof(cx_testing_allocator_s)); 3.123 -} 3.124 - 3.125 -bool cxTestingAllocatorVerify(void) { 3.126 - return cx_testing_allocator_data.live == 0 3.127 - && cx_testing_allocator_data.alloc_failed == 0 && cx_testing_allocator_data.free_failed == 0 3.128 - && cx_testing_allocator_data.alloc_total == cx_testing_allocator_data.free_total; 3.129 -}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/test/util_allocator.cpp Sat Apr 16 20:17:01 2022 +0200 4.3 @@ -0,0 +1,161 @@ 4.4 +/* 4.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 4.6 + * 4.7 + * Copyright 2021 Mike Becker, Olaf Wintermann All rights reserved. 4.8 + * 4.9 + * Redistribution and use in source and binary forms, with or without 4.10 + * modification, are permitted provided that the following conditions are met: 4.11 + * 4.12 + * 1. Redistributions of source code must retain the above copyright 4.13 + * notice, this list of conditions and the following disclaimer. 4.14 + * 4.15 + * 2. Redistributions in binary form must reproduce the above copyright 4.16 + * notice, this list of conditions and the following disclaimer in the 4.17 + * documentation and/or other materials provided with the distribution. 4.18 + * 4.19 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 4.20 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4.21 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4.22 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 4.23 + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 4.24 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 4.25 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 4.26 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 4.27 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 4.28 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4.29 + * POSSIBILITY OF SUCH DAMAGE. 4.30 + */ 4.31 + 4.32 +#include "util_allocator.h" 4.33 + 4.34 +void *cx_malloc_testing(void *d, size_t n) { 4.35 + auto data = reinterpret_cast<CxTestingAllocator *>(d); 4.36 + void *ptr = malloc(n); 4.37 + data->alloc_total++; 4.38 + if (ptr == nullptr) { 4.39 + data->alloc_failed++; 4.40 + } else { 4.41 + data->tracked.insert(ptr); 4.42 + } 4.43 + return ptr; 4.44 +} 4.45 + 4.46 +void *cx_realloc_testing(void *d, void *mem, size_t n) { 4.47 + auto data = reinterpret_cast<CxTestingAllocator *>(d); 4.48 + void *ptr = realloc(mem, n); 4.49 + if (ptr == mem) { 4.50 + return ptr; 4.51 + } else { 4.52 + data->alloc_total++; 4.53 + if (ptr == nullptr) { 4.54 + data->alloc_failed++; 4.55 + } else { 4.56 + data->free_total++; 4.57 + if (data->tracked.erase(mem) == 0) { 4.58 + data->free_failed++; 4.59 + } 4.60 + data->tracked.insert(ptr); 4.61 + } 4.62 + return ptr; 4.63 + } 4.64 +} 4.65 + 4.66 +void *cx_calloc_testing(void *d, size_t nelem, size_t n) { 4.67 + auto data = reinterpret_cast<CxTestingAllocator *>(d); 4.68 + void *ptr = calloc(nelem, n); 4.69 + data->alloc_total++; 4.70 + if (ptr == nullptr) { 4.71 + data->alloc_failed++; 4.72 + } else { 4.73 + data->tracked.insert(ptr); 4.74 + } 4.75 + return ptr; 4.76 +} 4.77 + 4.78 +void cx_free_testing(void *d, void *mem) { 4.79 + auto data = reinterpret_cast<CxTestingAllocator *>(d); 4.80 + data->free_total++; 4.81 + if (data->tracked.erase(mem) == 0) { 4.82 + data->free_failed++; 4.83 + // do not even attempt to free mem, because it is likely to segfault 4.84 + } else { 4.85 + free(mem); 4.86 + } 4.87 +} 4.88 + 4.89 +cx_allocator_class cx_testing_allocator_class = { 4.90 + cx_malloc_testing, 4.91 + cx_realloc_testing, 4.92 + cx_calloc_testing, 4.93 + cx_free_testing 4.94 +}; 4.95 + 4.96 +CxTestingAllocator::CxTestingAllocator() : CxAllocator() { 4.97 + cl = &cx_testing_allocator_class; 4.98 + data = this; 4.99 +} 4.100 + 4.101 +bool CxTestingAllocator::verify() const { 4.102 + return tracked.empty() && alloc_failed == 0 && free_failed == 0 && alloc_total == free_total; 4.103 +} 4.104 + 4.105 +// SELF-TEST 4.106 + 4.107 +#include <gtest/gtest.h> 4.108 + 4.109 +TEST(TestingAllocator, ExpectFree) { 4.110 + CxTestingAllocator allocator; 4.111 + 4.112 + ASSERT_TRUE(allocator.verify()); 4.113 + auto ptr = cxMalloc(&allocator, 16); 4.114 + ASSERT_NE(ptr, nullptr); 4.115 + EXPECT_FALSE(allocator.verify()); 4.116 + 4.117 + cxFree(&allocator, ptr); 4.118 + EXPECT_TRUE(allocator.verify()); 4.119 +} 4.120 + 4.121 +TEST(TestingAllocator, DetectDoubleFree) { 4.122 + CxTestingAllocator allocator; 4.123 + 4.124 + ASSERT_TRUE(allocator.verify()); 4.125 + auto ptr = cxMalloc(&allocator, 16); 4.126 + ASSERT_NE(ptr, nullptr); 4.127 + 4.128 + cxFree(&allocator, ptr); 4.129 + EXPECT_TRUE(allocator.verify()); 4.130 + ASSERT_NO_FATAL_FAILURE(cxFree(&allocator, ptr)); 4.131 + EXPECT_FALSE(allocator.verify()); 4.132 +} 4.133 + 4.134 +TEST(TestingAllocator, FreeUntracked) { 4.135 + CxTestingAllocator allocator; 4.136 + 4.137 + auto ptr = malloc(16); 4.138 + ASSERT_TRUE(allocator.verify()); 4.139 + ASSERT_NO_FATAL_FAILURE(cxFree(&allocator, ptr)); 4.140 + EXPECT_FALSE(allocator.verify()); 4.141 + ASSERT_NO_FATAL_FAILURE(free(ptr)); 4.142 +} 4.143 + 4.144 +TEST(TestingAllocator, FullLifecycleWithRealloc) { 4.145 + CxTestingAllocator allocator; 4.146 + ASSERT_TRUE(allocator.verify()); 4.147 + auto ptr = cxMalloc(&allocator, 16); 4.148 + ASSERT_NE(ptr, nullptr); 4.149 + EXPECT_EQ(allocator.tracked.size(), 1); 4.150 + ptr = cxRealloc(&allocator, ptr, 256); 4.151 + ASSERT_NE(ptr, nullptr); 4.152 + EXPECT_EQ(allocator.tracked.size(), 1); 4.153 + cxFree(&allocator, ptr); 4.154 + EXPECT_TRUE(allocator.verify()); 4.155 +} 4.156 + 4.157 +TEST(TestingAllocator, CallocInitializes) { 4.158 + CxTestingAllocator allocator; 4.159 + const char* zeros[16] = {0}; 4.160 + auto ptr = cxCalloc(&allocator, 16, 1); 4.161 + EXPECT_EQ(memcmp(ptr, zeros, 16), 0); 4.162 + cxFree(&allocator, ptr); 4.163 + EXPECT_TRUE(allocator.verify()); 4.164 +}
5.1 --- a/test/util_allocator.h Sat Apr 16 18:02:10 2022 +0200 5.2 +++ b/test/util_allocator.h Sat Apr 16 20:17:01 2022 +0200 5.3 @@ -31,60 +31,44 @@ 5.4 5.5 #include "cx/allocator.h" 5.6 5.7 -#ifdef __cplusplus 5.8 -extern "C" { 5.9 -#endif 5.10 +#include <set> 5.11 5.12 -#define CX_TESTING_ALLOCATOR_MAX_LIVE 1024 5.13 - 5.14 -typedef struct { 5.15 +struct CxTestingAllocator : public CxAllocator { 5.16 /** 5.17 * Total number of all allocations (malloc, calloc, realloc). 5.18 * A realloc() does only count when the memory has to be moved. 5.19 */ 5.20 - int alloc_total; 5.21 + unsigned alloc_total = 0; 5.22 /** 5.23 * Number of failed allocations (malloc, calloc, realloc). 5.24 */ 5.25 - int alloc_failed; 5.26 + unsigned alloc_failed = 0; 5.27 /** 5.28 * Total number of freed pointers. 5.29 * A reallocation also counts as a free when the memory has to be moved. 5.30 */ 5.31 - int free_total; 5.32 + unsigned free_total = 0; 5.33 /** 5.34 * Number of failed free invocations. 5.35 * A free() is considered failed, if it has not been performed on tracked memory. 5.36 */ 5.37 - int free_failed; 5.38 + unsigned free_failed = 0; 5.39 /** 5.40 - * Number of memory blocks that are currently live (and tracked). 5.41 - * The maximum number of tracked blocks is defined in #CX_TESTING_ALLOCATOR_MAX_LIVE. 5.42 + * The set of tracked memory blocks. 5.43 */ 5.44 - int live; 5.45 + std::set<void *> tracked; 5.46 + 5.47 /** 5.48 - * The array of tracked memory blocks. 5.49 + * Constructs a new testing allocator. 5.50 */ 5.51 - void *tracked[CX_TESTING_ALLOCATOR_MAX_LIVE]; 5.52 -} cx_testing_allocator_s; 5.53 + CxTestingAllocator(); 5.54 5.55 -extern CxAllocator *cxTestingAllocator; 5.56 - 5.57 -/** 5.58 - * Resets the testing allocator information. 5.59 - * This function SHOULD be called prior to any use of this allocator. 5.60 - */ 5.61 -void cxTestingAllocatorReset(void); 5.62 - 5.63 -/** 5.64 - * Checks whether all allocated memory is properly freed and no failed (de)allocations happened. 5.65 - * 5.66 - * @return true on success, false if there was any problem 5.67 - */ 5.68 -bool cxTestingAllocatorVerify(void); 5.69 - 5.70 -#ifdef __cplusplus 5.71 -}; /* extern "C" */ 5.72 -#endif 5.73 + /** 5.74 + * Verifies that all allocated memory blocks are freed and no free occurred twice. 5.75 + * 5.76 + * @return true iff all tracked allocations / deallocations were valid 5.77 + */ 5.78 + bool verify() const; 5.79 +}; 5.80 5.81 #endif /* UCX_UTIL_ALLOCATOR_H */