/
MemoryManager.cpp
122 lines (102 loc) · 3.64 KB
/
MemoryManager.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include "MemoryManager.h"
MemoryManager::MemoryManager() : file("MemoryLeaks.log")
{
// Is file Opened?
assert(file.is_open());
// Writing of the memory leak file header
file << " ========================================" << std::endl;
file << " Memory leak tracker " << std::endl;
file << " ========================================" << std::endl << std::endl;
}
MemoryManager::~MemoryManager()
{
if (blocks.empty())
{
// No leak
file << std::endl;
file << " ========================================" << std::endl;
file << " No leak detected, congratulations ! " << std::endl;
file << " ========================================" << std::endl;
}
else
{
// Leaks detected
file << std::endl;
file << " ========================================" << std::endl;
file << " Some leaks have been detected " << std::endl;
file << " ========================================" << std::endl;
file << std::endl;
reportLeaks();
}
}
MemoryManager& MemoryManager::get()
{
static MemoryManager inst;
return inst;
}
void MemoryManager::reportLeaks()
{
// leaks detail
std::size_t totalSize = 0;
for (blockMap::iterator it = blocks.begin(); it != blocks.end(); ++it)
{
// Add block size
totalSize += it->second.size;
// Writing current block informations into output file
file << "-> 0x" << it->first
<< " | " << std::setw(7) << std::setfill(' ') << static_cast<int>(it->second.size) << " bytes"
<< " | " << it->second.file.getFileName() << " (" << it->second.line << ")" << std::endl;
// Memory release
free(it->first);
}
// Write all memory leaks
file << std::endl << std::endl << "-- "
<< static_cast<int>(blocks.size()) << " not released block(s), "
<< static_cast<int>(totalSize) << " bytes --"
<< std::endl;
}
void* MemoryManager::allocate(std::size_t size, const File& f, int line, bool tab)
{
// Memory allocation
void* ptr = malloc(size);
// Add block to the allocated block list
block newBlock;
newBlock.size = size;
newBlock.file = f;
newBlock.line = line;
newBlock.tab = tab;
blocks[ptr] = newBlock;
// Writing in the output file
file << "++ Allocation | 0x" << ptr
<< " | " << std::setw(7) << std::setfill(' ') << static_cast<int>(newBlock.size) << " bytes"
<< " | " << newBlock.file.getFileName() << " (" << newBlock.line << ")" << std::endl;
return ptr;
}
void MemoryManager::desallocate(void* ptr, bool tab)
{
// Find the address in the allocated blocks
blockMap::iterator it = blocks.find(ptr);
// If the block isn't allocated, destroy the block and return
if (it == blocks.end())
{
free(ptr);
return;
}
// If the allocation type does not correspond, an error is generated
assert(it->second.tab == tab);
// Else, delete the block and write them in the output file
file << "-- Desallocation | 0x" << ptr
<< " | " << std::setw(7) << std::setfill(' ') << static_cast<int>(it->second.size) << " bytes"
<< " | " << deleteStack.top().file.getFileName() << " (" << deleteStack.top().line << ")" << std::endl;
blocks.erase(it);
deleteStack.pop();
// destroy block
free(ptr);
}
void MemoryManager::nextDelete(const File& file, int line)
{
block del;
del.file = file;
del.line = line;
deleteStack.push(del);
}