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