这篇文章终于是贴出了我们的源代码,实现每个功能也是花费了许多时间,大家在编写的时候可以多花点时间,多尝试,多看就能写出来。
老师的要求不能在程序里面使用malloc,new什么的,有要求使用链表,所以困扰了很久,在同学的启发下可以直接申请一块数组空间,然后再在这个数组空间下进行操作。
具体这个malloc的实现方法,就是申请空间的时候,如果开始里面没有区块,或者空着的区块就计算它要多少空间,在申请的数组空间上切下来一部分给它,要是有空着的区块>=申请的,就把这块区块给它,如果给的太大了,就把能比Header区大的空间的空间切出来变成一个新的区块,如果只能切比header小的空间,那个小空间就变成了内部碎片了。
free是会在释放某个区块的时候,检查附近的区块是不是空的,是的话,就把他们合在一起减少外部碎片的产生。
先产生的两个区块分别变成首尾的区块,新的区块会从首区块指向旧一点的区块,直到尾区块。
PS:本篇只贴出源代码,为了防止学弟,学妹直接复制,其他的讨论,测试不予贴出。
1 /* 2 * @ysy_zake 4/26/2017 3 * */ 4 #include <stdio.h> 5 #include <unistd.h> 6 #include <stdlib.h> 7 8 #define sizeOfBlock 24//Headerのサイズを決めます。 9 static size_t kkkkkk[20000];//配列でスペースを申請します 10 static void *tempaddress = kkkkkk;//一時的に今のアドレスをキープします 11 typedef struct Header { 12 unsigned elementSize;//実際のブロックのサイズ 13 struct Header *pre, *next;// 前駆と後継ポインタ 14 int free;//空いているかを示し//1空的、0不是空的 15 int filling;// アドレスをアライメントしやすいため、フィラーします。 16 void *pmc;//アドレスの正しさを確認するように使います。 17 char data[1]; 18 } h_header;//h_headerはHeader*別名であり 19 typedef struct Header *t_header;//t_headerはHeader*別名であり 20 t_header temp = NULL;//空きポインタをNULLに初期化します。 21 t_header getmmm(size_t sss) {//配列のアドレスからスペースを割り当てます 22 t_header temppppp = (t_header) tempaddress; 23 size_t fdf = ((size_t) temppppp + (size_t) sss - (size_t) kkkkkk); 24 if (fdf > 20000) {//もしオーバーフローが発生したらNULLを戻ります。 25 26 return NULL; 27 } 28 temppppp += sss; 29 tempaddress = temppppp; 30 return (t_header) tempaddress;//申請した新たなアドレスを戻ります。 31 } 32 33 void *myAlloc(size_t elementSizeTemp) {//オリジナルなmallocであり 34 if ((int) elementSizeTemp < 0) {//sizeはゼロよりおおきい必要があります 35 printf("ERROR size<0!"); 36 system("pause"); 37 exit(1); 38 } 39 if (elementSizeTemp < 24) {//sizeはheaderよりおおきい必要があります 40 printf("ERROR size have to bigger than 24!"); 41 system("pause"); 42 exit(1); 43 } 44 //アライメントします 45 size_t tempSize = elementSizeTemp; 46 t_header curBlock = NULL; 47 t_header finBlock, tempBlock;//finBlockは前のブラック 48 if (elementSizeTemp & 0x7 != 0) {//ブロックは8の倍数ではなっかたら、調整します 49 ((tempSize >> 3) + 1) << 3; 50 } 51 if (temp) {//tempはNULLですかを判断します 52 //NULLではなっかたら 53 //first-fit ブラックを探す 54 tempBlock = (t_header) temp; 55 while (tempBlock && !(tempBlock->free && tempBlock->elementSize >= tempSize)) {//ブラックの中で適当なブラックを探す 56 finBlock = tempBlock; 57 tempBlock = tempBlock->next; 58 } 59 curBlock = tempBlock; 60 if (curBlock) { 61 //ブラックがあったら、このブラックを 62 if ((curBlock->elementSize - tempSize) >= sizeOfBlock) { 63 t_header newblock;//新たなブラックを分離作る 64 newblock = curBlock + tempSize; 65 newblock->pmc = newblock->data; 66 newblock->elementSize = curBlock->elementSize - tempSize - sizeOfBlock; 67 newblock->next = curBlock->next; 68 newblock->free = 1; 69 curBlock->elementSize = tempSize; 70 curBlock->next = newblock; 71 } else { 72 printf("size:%d", tempBlock->elementSize); 73 printf("Internal fragmentation happened!"); 74 printf("\n"); 75 } 76 curBlock->free = 0;//今のブラックを使用中と設定します 77 } else { 78 //ブラックがなかったら、新たなブラックを作る 79 t_header newhead, temphd; 80 temphd = temp->next; 81 newhead = getmmm(elementSizeTemp); 82 if (newhead == NULL) {//もしオーバーフローが発生したら、判断します、プログラムを中止します 83 printf("Error overflow!"); 84 system("pause"); 85 exit(1); 86 } 87 newhead->pmc = newhead->data; 88 newhead->free = 0; 89 newhead->elementSize = elementSizeTemp; 90 newhead->next = temphd; 91 temp->next = newhead; 92 curBlock = newhead; 93 } 94 } else {//tempはNULLなら 95 curBlock = getmmm(elementSizeTemp);//新たなtempを作ります 96 if (curBlock == NULL) {//オーバーフローが発生したら、判断します、プログラムを中止します 97 printf("Error overflow!"); 98 system("pause"); 99 exit(1); 100 } 101 curBlock->free = 0; 102 curBlock->elementSize = elementSizeTemp; 103 curBlock->next = NULL; 104 curBlock->pre = NULL; 105 temp = curBlock; 106 } 107 return (void *) curBlock;//失敗したときNULLをもどります 108 } 109 110 t_header get_block(void *p) {//HEADERのアドレスが間違えた時元のアドレスに戻ります 111 t_header t = (t_header) p; 112 p = t->pmc - sizeOfBlock; 113 return (t_header) p; 114 } 115 116 int validAddr(void *p) {//アドレスは正しいか判断します 117 t_header tt = (t_header) p; 118 if (temp) { 119 if (p > temp && p <= tempaddress) { 120 tt->pmc -= sizeOfBlock; 121 void *t = tt->pmc; 122 123 return (p == t);//pmcのなかで保存しているアドレスと今のアドレスを比べる 124 } 125 } 126 return 0; 127 } 128 129 //ブラックを合体します 130 t_header fusion(t_header b) { 131 if (b->next && b->next->free) {//次のブラックと合体します 132 b->elementSize += sizeOfBlock + b->next->elementSize; 133 b->next = b->next->next; 134 if (b->next) 135 b->next->pre = b; 136 } 137 return b; 138 } 139 140 void myFree(void *block) {//オリジナルなFREE 141 if (block == NULL) {//このポインタはNULLか判断します 142 printf("Error Can‘t free a NULL!"); 143 return; 144 } 145 t_header curBlock; 146 //curBlock = (t_header)block; 147 if (validAddr(block)) {//今のアドレスは正しいか判断します 148 curBlock = (t_header) block; 149 150 } else { 151 curBlock = get_block(block);//アドレスが正しくないなら、修正します 152 } 153 154 curBlock->free = 1; 155 if (curBlock->pre && curBlock->pre->free)//もし上のブラックは空いています、これとうえのブラック合体します 156 curBlock = fusion(curBlock->pre); 157 if (curBlock->next)//もし次のブラックは空いています、これとうえのブラック合体します 158 fusion(curBlock); 159 curBlock = temp; 160 while (curBlock->next && (curBlock->next->free == 1)) {//ブラックの中であいているブラクラがあるか 161 curBlock = curBlock->next; 162 } 163 if (!(curBlock->next)) {//全てなブッラクはあいています、入り口のTEMPをNULLと設定します 164 temp = NULL; 165 } 166 167 } 168 169 void printout() {//中のブラックの状況を表します 170 t_header tempheader; 171 tempheader = temp; 172 while (tempheader) { 173 printf("size:%d free:%d\n", tempheader->elementSize, tempheader->free); 174 tempheader = tempheader->next; 175 } 176 } 177 178 void Exterfrag() { 179 t_header tempBlock = (t_header) temp; 180 while (tempBlock && !(tempBlock->free)) { 181 tempBlock = tempBlock->next; 182 } 183 if (tempBlock != NULL) { 184 printf("size:%d", tempBlock->elementSize); 185 printf("External fragmentation happened!"); 186 printf("\n"); 187 } 188 } 189 190 int main() { 191 int *ppp0 = (int *) myAlloc(10 * sizeof(int));//40これは入り口のTEMPになにます 192 int *ppp1 = (int *) myAlloc(20 * sizeof(int));//80これは最後 193 int *ppp2 = (int *) myAlloc(50 * sizeof(int));//200 194 int *ppp3 = (int *) myAlloc(70 * sizeof(int));//280 195 myFree(ppp3); 196 int *ppp4 = (int *) myAlloc(30 * sizeof(int));//120三番目 197 int *ppp5 = (int *) myAlloc(11 * sizeof(int));//44これは二番目 198 printout(); 199 Exterfrag(); 200 201 system("pause"); 202 return 0; 203 }
本人第一次写博客,要是有什么不好的地方请评论留言提出来,要是有帮上忙,请评论留个赞也行,谢谢。
时间: 2024-10-23 12:16:26