C++ Library Extensions 2022.12.09
To help learn modern C++ programming
cpg_track_new.hpp
Go to the documentation of this file.
1#ifndef CPG_TRACK_NEW_HPP
2#define CPG_TRACK_NEW_HPP
3
4#ifndef NOMINMAX
5#define NOMINMAX
6#endif
7
8/*
9 From "C++17 - The Complete Guide - By Nicolai M. Josuttis"
10 Minor Correction By Thomas Kim
11*/
12
13#include <memory_resource>
14#include <new> // for std::align_val_t
15#include <cstdio> // for printf()
16#include <cstdlib> // for malloc() and aligned_alloc()
17#ifdef _MSC_VER
18#include <malloc.h> // for _aligned_malloc() and _aligned_free()
19#endif
20
22{
23 class TrackNew
24 {
25 private:
26 static inline int numMalloc = 0; // num malloc calls
27 static inline size_t sumSize = 0; // bytes allocated so far
28 static inline bool doTrace = false; // tracing enabled
29 static inline bool inNew = false; // don't track output inside new overloads
30 public:
31 static void reset()
32 {
33 // reset new/memory counters
34 numMalloc = 0;
35 sumSize = 0;
36 }
37
38 static void trace(bool b)
39 {
40 // enable/disable tracing
41 doTrace = b;
42 }
43
44 // implementation of tracked allocation:
45 static void* allocate(std::size_t size, std::size_t align, const char* call)
46 {
47 // track and trace the allocation:
48 ++numMalloc;
49 sumSize += size;
50 void* p;
51
52 if (align == 0)
53 {
54 p = std::malloc(size);
55 }
56 else
57 {
58 #ifdef _WIN32
59 p = _aligned_malloc(size, align);
60 #else
61 p = std::aligned_alloc(size, align);
62 #endif
63 }
64
65 if (doTrace)
66 {
67 // DON'T use std::cout here because it might allocate memory
68 // while we are allocating memory (core dump at best)
69 printf("#%d %s ", numMalloc, call);
70 printf("(%zu bytes, ", size);
71 if (align > 0)
72 {
73 printf("%zu-byte aligned) ", align);
74 }
75 else
76 {
77 printf("def-aligned) ");
78 }
79
80 printf("=> %p (total: %zu bytes)\n", (void*)p, sumSize);
81 }
82
83 return p;
84 }
85
86 static void status()
87 {
88 // print current state
89 printf("%d allocations for %zu bytes\n", numMalloc, sumSize);
90 }
91 };
92}
93// end of namespace cpg::track_new
94
95 [[nodiscard]]
96 void* operator new (std::size_t size)
97 {
98 return cpg::track_new::TrackNew::allocate(size, 0, "::new");
99 }
100
101 [[nodiscard]]
102 void* operator new (std::size_t size, std::align_val_t align)
103 {
104 return cpg::track_new::TrackNew::allocate(size, static_cast<size_t>(align), "::new aligned");
105 }
106
107 [[nodiscard]]
108 void* operator new[] (std::size_t size)
109 {
110 return cpg::track_new::TrackNew::allocate(size, 0, "::new[]");
111 }
112
113 [[nodiscard]]
114 void* operator new[] (std::size_t size, std::align_val_t align)
115 {
116 return cpg::track_new::TrackNew::allocate(size, static_cast<size_t>(align), "::new[] aligned");
117 }
118
119 // ensure deallocations match:
120 void operator delete (void* p) noexcept
121 {
122 std::free(p);
123 }
124
125 void operator delete (void* p, std::size_t) noexcept
126 {
127 ::operator delete(p);
128 }
129
130 void operator delete (void* p, std::align_val_t) noexcept
131 {
132 #ifdef WIN32
133 _aligned_free(p); // Windows API
134 #else
135 std::free(p); // C++17 API
136 #endif
137 }
138
139 void operator delete (void* p, std::size_t, std::align_val_t align) noexcept
140 {
141 ::operator delete(p, align);
142 }
143
144#define Cpg_TrackNewReset() cpg::track_new::TrackNew::reset()
145#define Cpg_TrackNewStatus() cpg::track_new::TrackNew::status()
146
147#endif // CPG_TRACK_NEW_HPP
static void * allocate(std::size_t size, std::size_t align, const char *call)
static void trace(bool b)