-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcheckerbase.c
115 lines (98 loc) · 3.12 KB
/
checkerbase.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
/*--------------------------------------------------------------------*/
/* checkerbase.c */
/* Author: Bob Dondero */
/*--------------------------------------------------------------------*/
#include "checkerbase.h"
#include <stdio.h>
#include <assert.h>
/* In lieu of a boolean data type. */
enum {FALSE, TRUE};
/*--------------------------------------------------------------------*/
int Checker_isValid(Chunk_T oHeapStart, Chunk_T oHeapEnd,
Chunk_T oFreeList)
{
Chunk_T oChunk;
Chunk_T oPrevChunk;
Chunk_T oTortoiseChunk;
Chunk_T oHareChunk;
/* Do oHeapStart and oHeapEnd have non-NULL values? */
if (oHeapStart == NULL)
{
fprintf(stderr, "The heap start is uninitialized\n");
return FALSE;
}
if (oHeapEnd == NULL)
{
fprintf(stderr, "The heap end is uninitialized\n");
return FALSE;
}
/* If the heap is empty, is the free list empty too? */
if (oHeapStart == oHeapEnd)
{
if (oFreeList == NULL)
return TRUE;
else
{
fprintf(stderr, "The heap is empty, but the list is not.\n");
return FALSE;
}
}
/* Traverse memory. */
for (oChunk = oHeapStart;
oChunk != NULL;
oChunk = Chunk_getNextInMem(oChunk, oHeapEnd))
/* Is the chunk valid? */
if (! Chunk_isValid(oChunk, oHeapStart, oHeapEnd))
{
fprintf(stderr, "Traversing memory detected a bad chunk\n");
return FALSE;
}
/* Is the list devoid of cycles? Use Floyd's algorithm to find out.
See the Wikipedia "Cycle detection" page for a description. */
oTortoiseChunk = oFreeList;
oHareChunk = oFreeList;
if (oHareChunk != NULL)
oHareChunk = Chunk_getNextInList(oHareChunk);
while (oHareChunk != NULL)
{
if (oTortoiseChunk == oHareChunk)
{
fprintf(stderr, "The list has a cycle\n");
return FALSE;
}
/* Move oTortoiseChunk one step. */
oTortoiseChunk = Chunk_getNextInList(oTortoiseChunk);
/* Move oHareChunk two steps, if possible. */
oHareChunk = Chunk_getNextInList(oHareChunk);
if (oHareChunk != NULL)
oHareChunk = Chunk_getNextInList(oHareChunk);
}
/* Traverse the free list. */
oPrevChunk = NULL;
for (oChunk = oFreeList;
oChunk != NULL;
oChunk = Chunk_getNextInList(oChunk))
{
/* Is the chunk valid? */
if (! Chunk_isValid(oChunk, oHeapStart, oHeapEnd))
{
fprintf(stderr, "Traversing the list detected a bad chunk\n");
return FALSE;
}
/* Is the chunk in the proper place in the list? */
if ((oPrevChunk != NULL) && (oPrevChunk >= oChunk))
{
fprintf(stderr, "The list is unordered\n");
return FALSE;
}
/* Is the previous chunk in memory in use? */
if ((oPrevChunk != NULL) &&
(Chunk_getNextInMem(oPrevChunk, oHeapEnd) == oChunk))
{
fprintf(stderr, "The heap contains contiguous free chunks\n");
return FALSE;
}
oPrevChunk = oChunk;
}
return TRUE;
}