forked from waynegramlich/fiducials
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Memory.c
130 lines (114 loc) · 4.26 KB
/
Memory.c
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
123
124
125
126
127
128
129
130
// Copyright (c) 2013-2014 by Wayne C. Gramlich. All rights reserved.
#include <assert.h>
#include <stdlib.h>
#include "File.h"
#include "Memory.h"
#include "Unsigned.h"
#if defined(MEMORY_LEAK_CHECK)
static File Memory__allocate_file = (File)0;
static File Memory__free_file = (File)0;
static Memory Memory__leak = (Memory)0;
#endif // defined(MEMORY_LEAK_CHECK)
/// @brief Allocates *bytes* of memory and returns a pointer to it.
/// @param bytes is the number of bytes to allocate.
/// @param from is a debugging string.
/// @returns a pointer to the allocated memory chunk.
///
/// *Memory__allocate*() will allocated and return a pointer to a chunk
/// of *bytes* memory.
Memory Memory__allocate(Unsigned bytes, String from) {
Memory memory = (Memory)malloc(bytes);
assert (memory != (Memory)0);
#if defined(MEMORY_LEAK_CHECK)
// Make sure that the logging files are open:
if (Memory__allocate_file == (File)0) {
Memory__allocate_file = File__open("/tmp/memory_allocate.log","w");
Memory__free_file = File__open("/tmp/memory_free.log","w");
assert (Memory__allocate_file != (File)0);
assert (Memory__free_file != (File)0);
}
File__format(Memory__allocate_file, "0x%08x %s\n", memory, from);
File__flush(Memory__allocate_file);
// Now check for a memory leak match:
if (memory == Memory__leak) {
Memory__leak_found(memory);
}
#endif // defined(MEMORY_LEAK_CHECK)
return memory;
}
#if defined(MEMORY_LEAK_CHECK)
void Memory__leak_check(Memory memory) {
Memory__leak = memory;
}
void Memory__leak_found(Memory memory) {
// Plant break point here:
memory = memory;
}
#endif // defined(MEMORY_LEAK_CHECK)
/// @brief Releases the storage associated with *memory*.
/// @param memory to release.
///
/// *Memory__free*() will release the storage associated with *memory*.
void Memory__free(Memory memory) {
#if defined(MEMORY_LEAK_CHECK)
File__format(Memory__free_file, "0x%08x\n", memory);
File__flush(Memory__free_file);
#else
free(memory);
#endif // defined(MEMORY_LEAK_CHECK)
}
/// @brief Expands/contracts *memory* to be *new_size* bytes.
/// @param memory to expand or contract.
/// @param new_size is the new size of the memory segement.
/// @param from is a debugging string.
/// @returns *memory* or a copy of *memory*.
///
/// *Memory__reallocate*() will either *resize* *memory* to be *new_bytes*
/// bytes in size, or allocate a new chunk of memory that is *new_bytes* in
/// size. If the later case, the previous contents of memory is copied over
/// before releasing the original storage.
Memory Memory__reallocate(Memory memory, Unsigned new_size, String from) {
#if defined(MEMORY_LEAK_CHECK)
Memory new_memory = (Memory)malloc(new_size);
assert(new_memory != (Memory)0);
// This is a tad ugly. We do not know the old size of *memory*,
// but we need to copy the contents of *memory* into *new_memory*.
// The solution is to copy *new_size* bytes from *memory* to
// completely fill up *new_memory*. This may run off the end
// of *memory*, but it is unlikely that we cause a memory fault.
String new_string = (String)new_memory;
String old_string = (String)memory;
for (Unsigned index = 0; index < new_size; index++) {
new_string[index] = old_string[index];
}
// New record the reallocation as an allocate and a free:
assert(Memory__allocate_file != (File)0);
assert(Memory__free_file != (File)0);
File__format(Memory__allocate_file,
"0x%08x %s_0x%08x\n", new_memory, from, memory);
File__flush(Memory__allocate_file);
File__format(Memory__free_file, "0x%08x\n", memory);
File__flush(Memory__free_file);
// Now check for a memory leak match:
if (new_memory == Memory__leak) {
Memory__leak_found(new_memory);
}
#else
Memory new_memory = realloc(memory, new_size);
assert (new_memory != (Memory)0);
#endif // defined(MEMORY_LEAK_CHECK)
return new_memory;
}
/// @brief Return *unsigned1* as a *Memory* pointer.
/// @param unsigned1 is the value to be treated as *Memory*
/// @returns *unsigned1* as a *Memory* pointer.
///
/// *Unsigned__to_memory*() returns *unsigned1* as a *Memory* pointer.
Memory Unsigned__to_memory(Unsigned unsigned1) {
union {
Unsigned unsigned1;
Memory memory;
} convert;
convert.unsigned1 = unsigned1;
return convert.memory;
}