日本程序开发式自定义的malloc/free函数(三)-源代码(ソースコード)

这篇文章终于是贴出了我们的源代码,实现每个功能也是花费了许多时间,大家在编写的时候可以多花点时间,多尝试,多看就能写出来。

老师的要求不能在程序里面使用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

日本程序开发式自定义的malloc/free函数(三)-源代码(ソースコード)的相关文章

在.net桌面程序中自定义鼠标光标

有的时候,一个自定义的鼠标光标能给你的程序增色不少.本文这里介绍一下如何在.net桌面程序中自定义鼠标光标.由于.net的桌面程序分为WinForm和WPF两种,这里分别介绍一下. WinForm程序 对于WinForm程序,可以通过修改Control.Cursor属性来实现光标的修改,如果我们有光标文件的话,可以直接通过如下代码实现自定义光标: this.Cursor = new Cursor("myCursor.cur"); 但这种方式不是本文介绍的重点,本文主要介绍如何自己绘制光

黑马程序员——c语言学习心得——函数传递二维数组

黑马程序员——c语言学习心得——函数传递二维数组 -------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 一.定义指针的时候一定要初始化.   变量定义的时候给变量初始化,这是保证不出错的一个很好的习惯.尤其是在指针的使用上,如果我们没有给指针初始化,就会出现野指针,该指针的指向并不是我们所希望的,一旦错误的释放了这个指针,就会发生内存的访问.那么如何初始化指针变量呢,一般有以下几种方法:   1.初始化空指针   int* pInteger=N

Cocos2d-x下Lua调用自定义C++类和函数的最佳实践 -- 转

原地址: http://blog.segmentfault.com/hongliang/1190000000631630 Cocos2d-x下Lua调用自定义C++类和函数的最佳实践 关于cocos2d-x下Lua调用C++的文档看了不少,但没有一篇真正把这事给讲明白了,我自己也是个初学者,摸索了半天,总结如下: cocos2d-x下Lua调用C++这事之所以看起来这么复杂.网上所有的文档都没讲清楚,是因为存在5个层面的知识点: 1.在纯C环境下,把C函数注册进Lua环境,理解Lua和C之间可以

Delphi中Stringlist的自定义排序(将函数地址做为参数)

近日,在编制一个程序过程,因为数据量较小,就使用了stringlist来暂存数据.在使用过程中,遇到了一个问题.Stringlist字符串列表的默认排序方法是按ASCII码的方式进行排序,如3,10,9排序时,结果为10,3,9.不符合程序的要求,于是尝试着使用字符串列表的自主义排序方法,这时需要传入一个function类的参数,因为习惯于使用PYTHON语言,所以直接编写民了一个按数值降序排列的排序函数,并将函数名传给了stringlistrr的CustomSort方法,结果提示:Incomp

SUID或SGID程序中能不能用system函数

system()函数的声明和说明如下: 注意它的描述那里,system()执行一个由command参数定义的命令,通过调用/bin/sh -c命令来实现这个功能.也就是说它的逻辑是这样的! 进程调用system函数,system函数调用fork创建一个子进程,然后再调用exec函数来把这个子进程的正文段替换成/bin/sh命令的正文段.然后再由sh来执行exec将程序的正文段替换成command参数所代表的命令的正文段,例如,我的一个程序a.out来调用system函数来执行sleep 20命令

使用程序创建自定义Web部件Web Part

使用程序创建自定义Web部件Web Part 使用VS2010你可以通过程序创建自定义Web部件. 1. 以管理员身份打开VS2010.新建项目----空白SharePoint项目.命名MyFirstWebPart,点击确定. 2. 部署为场解决方案. 3. 右击项目添加新项目---Web Part.命名MyFirstWebPart. 4. 查看Web part代码文件,添加如下代码: 5. 点击F6查看能否成功生成项目. 6. 成功后设置断点,F5调试. 7. 调试完毕后,部署. 8. 在站点

自定义文件夹处理函数(Python)

#encoding: utf-8 #author: walker #date: 2017-06-15 #summary: 自定义文件夹处理函数,适用于python3.5+ import os import shutil import win32com.client #清空目录 def ClearDir(dir):     print('ClearDir ' + dir + '...')           for entry in os.scandir(dir):         if entr

如何在VS2013+QT5.3环境下使用自定义信号与槽函数

图1中标注出来的是VS2013中的QT界面设计师文件,双击默认打开的是Qt设计师工具. 在界面上面拉入一个PushButton,点击编辑信号与槽按钮进入编辑模式. 选择信号clicked(),发现可以从QWidget继承很多槽函数,暂时先选择close()槽函数,点OK 保存后,VS2013中有个文件“ui_testqt.h”会自动生成信号与槽的代码.此文件也是生成界面文件的源代码. 目前都是使用的默认的信号与槽函数,如果想触发自定义的槽函数呢?我们会想到可以直接修改ui_testqt.h里面的

自定义防SQL注入函数

/************************************************ *SQL防注入函数 *@time 2014年6月24日18:50:59 * */ public function safe_replace($string){ $string = str_replace('%20','',$string); $string = str_replace('%27','',$string); $string = str_replace('%2527','',$stri