Branch data Line data Source code
1 : : /*
2 : : * Copyright 2025 Jinwoo Sung
3 : : *
4 : : * Licensed under the Apache License, Version 2.0 (the "License");
5 : : * you may not use this file except in compliance with the License.
6 : : * You may obtain a copy of the License at
7 : : *
8 : : * http://www.apache.org/licenses/LICENSE-2.0
9 : : *
10 : : * Unless required by applicable law or agreed to in writing, software
11 : : * distributed under the License is distributed on an "AS IS" BASIS,
12 : : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 : : * See the License for the specific language governing permissions and
14 : : * limitations under the License.
15 : : */
16 : :
17 : : #pragma once
18 : :
19 : : #include <atomic>
20 : : #include <chrono>
21 : : #include <memory>
22 : : #include <mutex>
23 : : #include <string>
24 : : #include <unordered_map>
25 : : #include <vector>
26 : :
27 : : #include "wirestead/base/visibility.hpp"
28 : :
29 : : namespace wirestead {
30 : : namespace memory {
31 : :
32 : : /**
33 : : * @brief Memory allocation tracker for debugging and monitoring
34 : : *
35 : : * Tracks memory allocations and deallocations to detect leaks,
36 : : * monitor usage patterns, and provide debugging information.
37 : : */
38 : : class WIRESTEAD_API MemoryTracker {
39 : : public:
40 : : struct AllocationInfo {
41 : : void* ptr;
42 : : size_t size;
43 : : const char* file;
44 : : int line;
45 : : std::chrono::steady_clock::time_point timestamp;
46 : : const char* function;
47 : : };
48 : :
49 : : struct MemoryStats {
50 : : size_t total_allocations{0};
51 : : size_t total_deallocations{0};
52 : : size_t current_allocations{0};
53 : : size_t peak_allocations{0};
54 : : size_t total_bytes_allocated{0};
55 : : size_t total_bytes_deallocated{0};
56 : : size_t current_bytes_allocated{0};
57 : : size_t peak_bytes_allocated{0};
58 : : };
59 : :
60 : : // Singleton access
61 : : static MemoryTracker& instance();
62 : :
63 : : // Tracking methods
64 : : void track_allocation(void* ptr, size_t size, const char* file, int line, const char* function);
65 : : void track_deallocation(void* ptr);
66 : :
67 : : // Statistics
68 : : MemoryStats stats() const;
69 : : std::vector<AllocationInfo> current_allocations() const;
70 : : std::vector<AllocationInfo> leaked_allocations() const;
71 : :
72 : : // Control
73 : : void enable_tracking(bool enable = true);
74 : : void disable_tracking();
75 : : bool tracking_enabled() const;
76 : :
77 : : // Cleanup
78 : : void clear_tracking_data();
79 : :
80 : : // Debugging
81 : : void print_memory_report() const;
82 : : void print_leak_report() const;
83 : :
84 : : // Logger-based reporting (recommended for production)
85 : : void log_memory_report() const;
86 : : void log_leak_report() const;
87 : :
88 : : private:
89 : 8 : MemoryTracker() = default;
90 : 8 : ~MemoryTracker() = default;
91 : :
92 : : MemoryTracker(const MemoryTracker&) = delete;
93 : : MemoryTracker& operator=(const MemoryTracker&) = delete;
94 : :
95 : : mutable std::mutex allocations_mutex_;
96 : : std::unordered_map<void*, AllocationInfo> allocations_;
97 : : MemoryStats stats_;
98 : : std::atomic<bool> tracking_enabled_{true};
99 : : };
100 : :
101 : : /**
102 : : * @brief RAII helper for automatic memory tracking
103 : : */
104 : : class WIRESTEAD_API ScopedMemoryTracker {
105 : : public:
106 : : ScopedMemoryTracker(const char* file, int line, const char* function);
107 : : ~ScopedMemoryTracker();
108 : :
109 : : void track_allocation(void* ptr, size_t size);
110 : : void track_deallocation(void* ptr);
111 : :
112 : : private:
113 : : const char* file_;
114 : : int line_;
115 : : const char* function_;
116 : : };
117 : :
118 : : } // namespace memory
119 : : } // namespace wirestead
120 : :
121 : : // Convenience macros for automatic tracking
122 : : #ifdef WIRESTEAD_ENABLE_MEMORY_TRACKING
123 : : #define MEMORY_TRACK_ALLOCATION(ptr, size) \
124 : : wirestead::memory::MemoryTracker::instance().track_allocation(ptr, size, __FILE__, __LINE__, __FUNCTION__)
125 : :
126 : : #define MEMORY_TRACK_DEALLOCATION(ptr) wirestead::memory::MemoryTracker::instance().track_deallocation(ptr)
127 : :
128 : : #define MEMORY_TRACK_SCOPE() wirestead::memory::ScopedMemoryTracker _mem_tracker(__FILE__, __LINE__, __FUNCTION__)
129 : : #else
130 : : #define MEMORY_TRACK_ALLOCATION(ptr, size) ((void)0)
131 : : #define MEMORY_TRACK_DEALLOCATION(ptr) ((void)0)
132 : : #define MEMORY_TRACK_SCOPE() ((void)0)
133 : : #endif
|