malloc.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765
  1. // Copyright (c) Athena Dev Teams - Licensed under GNU GPL
  2. // For more information, see LICENCE in the main folder
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include "../common/malloc.h"
  7. #include "../common/core.h"
  8. #include "../common/showmsg.h"
  9. #ifdef MINICORE
  10. #undef LOG_MEMMGR
  11. #endif
  12. void* aMalloc_ (size_t size, const char *file, int line, const char *func)
  13. {
  14. #ifndef MEMWATCH
  15. void *ret = MALLOC(size);
  16. #else
  17. void *ret = mwMalloc(size, file, line);
  18. #endif
  19. // ShowMessage("%s:%d: in func %s: malloc %d\n",file,line,func,size);
  20. if (ret == NULL){
  21. ShowFatalError("%s:%d: in func %s: malloc error out of memory!\n",file,line,func);
  22. exit(1);
  23. }
  24. return ret;
  25. }
  26. void* aMallocA_ (size_t size, const char *file, int line, const char *func)
  27. {
  28. #ifndef MEMWATCH
  29. void *ret = MALLOCA(size);
  30. #else
  31. void *ret = mwMalloc(size, file, line);
  32. #endif
  33. // ShowMessage("%s:%d: in func %s: malloc %d\n",file,line,func,size);
  34. if (ret == NULL){
  35. ShowFatalError("%s:%d: in func %s: malloc error out of memory!\n",file,line,func);
  36. exit(1);
  37. }
  38. return ret;
  39. }
  40. void* aCalloc_ (size_t num, size_t size, const char *file, int line, const char *func)
  41. {
  42. #ifndef MEMWATCH
  43. void *ret = CALLOC(num, size);
  44. #else
  45. void *ret = mwCalloc(num, size, file, line);
  46. #endif
  47. // ShowMessage("%s:%d: in func %s: calloc %d %d\n",file,line,func,num,size);
  48. if (ret == NULL){
  49. ShowFatalError("%s:%d: in func %s: calloc error out of memory!\n", file, line, func);
  50. exit(1);
  51. }
  52. return ret;
  53. }
  54. void* aCallocA_ (size_t num, size_t size, const char *file, int line, const char *func)
  55. {
  56. #ifndef MEMWATCH
  57. void *ret = CALLOCA(num, size);
  58. #else
  59. void *ret = mwCalloc(num, size, file, line);
  60. #endif
  61. // ShowMessage("%s:%d: in func %s: calloc %d %d\n",file,line,func,num,size);
  62. if (ret == NULL){
  63. ShowFatalError("%s:%d: in func %s: calloc error out of memory!\n",file,line,func);
  64. exit(1);
  65. }
  66. return ret;
  67. }
  68. void* aRealloc_ (void *p, size_t size, const char *file, int line, const char *func)
  69. {
  70. #ifndef MEMWATCH
  71. void *ret = REALLOC(p, size);
  72. #else
  73. void *ret = mwRealloc(p, size, file, line);
  74. #endif
  75. // ShowMessage("%s:%d: in func %s: realloc %p %d\n",file,line,func,p,size);
  76. if (ret == NULL){
  77. ShowFatalError("%s:%d: in func %s: realloc error out of memory!\n",file,line,func);
  78. exit(1);
  79. }
  80. return ret;
  81. }
  82. char* aStrdup_ (const char *p, const char *file, int line, const char *func)
  83. {
  84. #ifndef MEMWATCH
  85. char *ret = STRDUP(p);
  86. #else
  87. char *ret = mwStrdup(p, file, line);
  88. #endif
  89. // ShowMessage("%s:%d: in func %s: strdup %p\n",file,line,func,p);
  90. if (ret == NULL){
  91. ShowFatalError("%s:%d: in func %s: strdup error out of memory!\n", file, line, func);
  92. exit(1);
  93. }
  94. return ret;
  95. }
  96. void aFree_ (void *p, const char *file, int line, const char *func)
  97. {
  98. // ShowMessage("%s:%d: in func %s: free %p\n",file,line,func,p);
  99. if (p)
  100. #ifndef MEMWATCH
  101. FREE(p);
  102. #else
  103. mwFree(p, file, line);
  104. #endif
  105. p = NULL;
  106. }
  107. #ifdef GCOLLECT
  108. void* _bcallocA(size_t size, size_t cnt)
  109. {
  110. void *ret = MALLOCA(size * cnt);
  111. if (ret) //malloc_set(ret, 0, size * cnt);
  112. malloc_set(ret, 0, size*cnt);
  113. return ret;
  114. }
  115. void* _bcalloc(size_t size, size_t cnt)
  116. {
  117. void *ret = MALLOC(size * cnt);
  118. if (ret) //malloc_set(ret, 0, size * cnt);
  119. malloc_set(ret, 0, size*cnt);
  120. return ret;
  121. }
  122. char* _bstrdup(const char *chr)
  123. {
  124. int len = strlen(chr);
  125. char *ret = (char*)MALLOC(len + 1);
  126. if (ret) memcpy(ret, chr, len + 1);
  127. return ret;
  128. }
  129. #endif
  130. #ifdef USE_MEMMGR
  131. /* USE_MEMMGR */
  132. /*
  133. * メモリマネージャ
  134. * malloc , free の処理を効率的に出来るようにしたもの。
  135. * 複雑な処理を行っているので、若干重くなるかもしれません。
  136. *
  137. * データ構造など(説明下手ですいません^^; )
  138. * ・メモリを複数の「ブロック」に分けて、さらにブロックを複数の「ユニット」
  139. * に分けています。ユニットのサイズは、1ブロックの容量を複数個に均等配分
  140. * したものです。たとえば、1ユニット32KBの場合、ブロック1つは32Byteのユ
  141. * ニットが、1024個集まって出来ていたり、64Byteのユニットが 512個集まって
  142. * 出来ていたりします。(padding,unit_head を除く)
  143. *
  144. * ・ブロック同士はリンクリスト(block_prev,block_next) でつながり、同じサイ
  145. * ズを持つブロック同士もリンクリスト(samesize_prev,samesize_nect) でつな
  146. * がっています。それにより、不要となったメモリの再利用が効率的に行えます。
  147. */
  148. /* ブロックに入るデータ量 */
  149. #define BLOCK_DATA_SIZE 80*1024
  150. /* 一度に確保するブロックの数。 */
  151. #define BLOCK_ALLOC 32
  152. /* ブロックのアライメント */
  153. #define BLOCK_ALIGNMENT 64
  154. /* ブロック */
  155. struct block {
  156. int block_no; /* ブロック番号 */
  157. struct block* block_prev; /* 前に確保した領域 */
  158. struct block* block_next; /* 次に確保した領域 */
  159. int samesize_no; /* 同じサイズの番号 */
  160. struct block* samesize_prev; /* 同じサイズの前の領域 */
  161. struct block* samesize_next; /* 同じサイズの次の領域 */
  162. size_t unit_size; /* ユニットのバイト数 0=未使用 */
  163. size_t unit_hash; /* ユニットのハッシュ */
  164. int unit_count; /* ユニットの数 */
  165. int unit_used; /* 使用済みユニット */
  166. char data[BLOCK_DATA_SIZE];
  167. };
  168. struct unit_head {
  169. struct block* block;
  170. size_t size;
  171. const char* file;
  172. int line;
  173. unsigned int checksum;
  174. };
  175. struct chunk {
  176. char *block;
  177. struct chunk *next;
  178. };
  179. static struct block* block_first = NULL;
  180. static struct block* block_last = NULL;
  181. static struct block* block_unused = NULL;
  182. /* ユニットへのハッシュ。80KB/64Byte = 1280個 */
  183. static struct block* unit_first[BLOCK_DATA_SIZE/BLOCK_ALIGNMENT]; /* 最初 */
  184. static struct block* unit_unfill[BLOCK_DATA_SIZE/BLOCK_ALIGNMENT]; /* 埋まってない */
  185. static struct block* unit_last[BLOCK_DATA_SIZE/BLOCK_ALIGNMENT]; /* 最後 */
  186. /* メモリを使い回せない領域用のデータ */
  187. struct unit_head_large {
  188. struct unit_head_large* prev;
  189. struct unit_head_large* next;
  190. struct unit_head unit_head;
  191. };
  192. static struct unit_head_large *unit_head_large_first = NULL;
  193. static struct chunk *chunk_first = NULL;
  194. static struct block* block_malloc(void);
  195. static void block_free(struct block* p);
  196. static void memmgr_info(void);
  197. static unsigned int memmgr_usage_bytes = 0;
  198. void* _mmalloc(size_t size, const char *file, int line, const char *func ) {
  199. int i;
  200. struct block *block;
  201. size_t size_hash;
  202. if (((long) size) < 0) {
  203. printf("_mmalloc: %d\n", size);
  204. return 0;
  205. }
  206. size_hash = (size+BLOCK_ALIGNMENT-1) / BLOCK_ALIGNMENT;
  207. if(size == 0) {
  208. return NULL;
  209. }
  210. memmgr_usage_bytes += size;
  211. /* ブロック長を超える領域の確保には、malloc() を用いる */
  212. /* その際、unit_head.block に NULL を代入して区別する */
  213. if(size_hash * BLOCK_ALIGNMENT > BLOCK_DATA_SIZE - sizeof(struct unit_head)) {
  214. #ifdef MEMWATCH
  215. struct unit_head_large* p = (struct unit_head_large*)mwMalloc(sizeof(struct unit_head_large) + size,file,line);
  216. #else
  217. struct unit_head_large* p = (struct unit_head_large*) MALLOC (sizeof(struct unit_head_large) + size);
  218. #endif
  219. if(p != NULL) {
  220. p->unit_head.block = NULL;
  221. p->unit_head.size = size;
  222. p->unit_head.file = file;
  223. p->unit_head.line = line;
  224. p->prev = NULL;
  225. if (unit_head_large_first == NULL)
  226. p->next = NULL;
  227. else {
  228. unit_head_large_first->prev = p;
  229. p->next = unit_head_large_first;
  230. }
  231. unit_head_large_first = p;
  232. *(int*)((char*)p + sizeof(struct unit_head_large) - sizeof(int) + size) = 0xdeadbeaf;
  233. return (char *)p + sizeof(struct unit_head_large) - sizeof(int);
  234. } else {
  235. ShowFatalError("Memory manager::memmgr_alloc failed (allocating %d+%d bytes at %s:%d).\n", sizeof(struct unit_head_large), size, file, line);
  236. exit(1);
  237. }
  238. }
  239. /* 同一サイズのブロックが確保されていない時、新たに確保する */
  240. if(unit_unfill[size_hash] == NULL) {
  241. block = block_malloc();
  242. if(unit_first[size_hash] == NULL) {
  243. /* 初回確保 */
  244. unit_first[size_hash] = block;
  245. unit_last[size_hash] = block;
  246. block->samesize_no = 0;
  247. block->samesize_prev = NULL;
  248. block->samesize_next = NULL;
  249. } else {
  250. /* 連結作業 */
  251. unit_last[size_hash]->samesize_next = block;
  252. block->samesize_no = unit_last[size_hash]->samesize_no + 1;
  253. block->samesize_prev = unit_last[size_hash];
  254. block->samesize_next = NULL;
  255. unit_last[size_hash] = block;
  256. }
  257. unit_unfill[size_hash] = block;
  258. block->unit_size = size_hash * BLOCK_ALIGNMENT + sizeof(struct unit_head);
  259. block->unit_count = (int)(BLOCK_DATA_SIZE / block->unit_size);
  260. block->unit_used = 0;
  261. block->unit_hash = size_hash;
  262. /* 未使用Flagを立てる */
  263. for(i=0;i<block->unit_count;i++) {
  264. ((struct unit_head*)(&block->data[block->unit_size * i]))->block = NULL;
  265. }
  266. }
  267. /* ユニット使用個数加算 */
  268. block = unit_unfill[size_hash];
  269. block->unit_used++;
  270. /* ユニット内を全て使い果たした */
  271. if(block->unit_count == block->unit_used) {
  272. do {
  273. unit_unfill[size_hash] = unit_unfill[size_hash]->samesize_next;
  274. } while(
  275. unit_unfill[size_hash] != NULL &&
  276. unit_unfill[size_hash]->unit_count == unit_unfill[size_hash]->unit_used
  277. );
  278. }
  279. /* ブロックの中の空きユニット捜索 */
  280. for(i=0;i<block->unit_count;i++) {
  281. struct unit_head *head = (struct unit_head*)(&block->data[block->unit_size * i]);
  282. if(head->block == NULL) {
  283. head->block = block;
  284. head->size = size;
  285. head->line = line;
  286. head->file = file;
  287. *(int*)((char*)head + sizeof(struct unit_head) - sizeof(int) + size) = 0xdeadbeaf;
  288. return (char *)head + sizeof(struct unit_head) - sizeof(int);
  289. }
  290. }
  291. // ここに来てはいけない。
  292. ShowFatalError("Memory manager::memmgr_malloc() serious error (allocating %d+%d bytes at %s:%d)\n", sizeof(struct unit_head_large), size, file, line);
  293. memmgr_info();
  294. exit(1);
  295. return NULL;
  296. };
  297. void* _mcalloc(size_t num, size_t size, const char *file, int line, const char *func ) {
  298. void *p = _mmalloc(num * size,file,line,func);
  299. //malloc_set(p,0,num * size);
  300. malloc_set(p,0,num*size);
  301. return p;
  302. }
  303. void* _mrealloc(void *memblock, size_t size, const char *file, int line, const char *func ) {
  304. size_t old_size;
  305. if(memblock == NULL) {
  306. return _mmalloc(size,file,line,func);
  307. }
  308. old_size = ((struct unit_head *)((char *)memblock - sizeof(struct unit_head) + sizeof(int)))->size;
  309. if(old_size > size) {
  310. // サイズ縮小 -> そのまま返す(手抜き)
  311. return memblock;
  312. } else {
  313. // サイズ拡大
  314. void *p = _mmalloc(size,file,line,func);
  315. if(p != NULL) {
  316. memcpy(p,memblock,old_size);
  317. }
  318. _mfree(memblock,file,line,func);
  319. return p;
  320. }
  321. }
  322. char* _mstrdup(const char *p, const char *file, int line, const char *func ) {
  323. if(p == NULL) {
  324. return NULL;
  325. } else {
  326. size_t len = strlen(p);
  327. char *string = (char *)_mmalloc(len + 1,file,line,func);
  328. memcpy(string,p,len+1);
  329. return string;
  330. }
  331. }
  332. void _mfree(void *ptr, const char *file, int line, const char *func ) {
  333. struct unit_head *head;
  334. size_t size_hash;
  335. if (ptr == NULL)
  336. return;
  337. head = (struct unit_head *)((char *)ptr - sizeof(struct unit_head) + sizeof(int));
  338. size_hash = (head->size+BLOCK_ALIGNMENT-1) / BLOCK_ALIGNMENT;
  339. if(head->block == NULL) {
  340. if(size_hash * BLOCK_ALIGNMENT > BLOCK_DATA_SIZE - sizeof(struct unit_head)) {
  341. /* malloc() で直に確保された領域 */
  342. struct unit_head_large *head_large = (struct unit_head_large *)((char *)ptr - sizeof(struct unit_head_large) + sizeof(int));
  343. if(
  344. *(int*)((char*)head_large + sizeof(struct unit_head_large) - sizeof(int) + head->size)
  345. != 0xdeadbeaf)
  346. {
  347. ShowError("Memory manager: args of aFree is overflowed pointer %s line %d\n", file, line);
  348. }
  349. if(head_large->prev) {
  350. head_large->prev->next = head_large->next;
  351. } else {
  352. unit_head_large_first = head_large->next;
  353. }
  354. if(head_large->next) {
  355. head_large->next->prev = head_large->prev;
  356. }
  357. head->block = NULL;
  358. memmgr_usage_bytes -= head->size;
  359. FREE (head_large);
  360. } else {
  361. ShowError("Memory manager: args of aFree is freed pointer %s:%d@%s\n", file, line, func);
  362. }
  363. ptr = NULL;
  364. return;
  365. } else {
  366. /* ユニット解放 */
  367. struct block *block = head->block;
  368. if((unsigned long)block % sizeof(struct block) != 0) {
  369. ShowError("Memory manager: args of aFree is not valid pointer %s line %d\n", file, line);
  370. } else if(*(int*)((char*)head + sizeof(struct unit_head) - sizeof(int) + head->size) != 0xdeadbeaf) {
  371. ShowError("Memory manager: args of aFree is overflowed pointer %s line %d\n", file, line);
  372. } else {
  373. head->block = NULL;
  374. memmgr_usage_bytes -= head->size;
  375. if(--block->unit_used == 0) {
  376. /* ブロックの解放 */
  377. if(unit_unfill[block->unit_hash] == block) {
  378. /* 空きユニットに指定されている */
  379. do {
  380. unit_unfill[block->unit_hash] = unit_unfill[block->unit_hash]->samesize_next;
  381. } while(
  382. unit_unfill[block->unit_hash] != NULL &&
  383. unit_unfill[block->unit_hash]->unit_count == unit_unfill[block->unit_hash]->unit_used
  384. );
  385. }
  386. if(block->samesize_prev == NULL && block->samesize_next == NULL) {
  387. /* 独立ブロックの解放 */
  388. unit_first[block->unit_hash] = NULL;
  389. unit_last[block->unit_hash] = NULL;
  390. unit_unfill[block->unit_hash] = NULL;
  391. } else if(block->samesize_prev == NULL) {
  392. /* 先頭ブロックの解放 */
  393. unit_first[block->unit_hash] = block->samesize_next;
  394. (block->samesize_next)->samesize_prev = NULL;
  395. } else if(block->samesize_next == NULL) {
  396. /* 末端ブロックの解放 */
  397. unit_last[block->unit_hash] = block->samesize_prev;
  398. (block->samesize_prev)->samesize_next = NULL;
  399. } else {
  400. /* 中間ブロックの解放 */
  401. (block->samesize_next)->samesize_prev = block->samesize_prev;
  402. (block->samesize_prev)->samesize_next = block->samesize_next;
  403. }
  404. block_free(block);
  405. } else {
  406. /* 空きユニットの再設定 */
  407. if(
  408. unit_unfill[block->unit_hash] == NULL ||
  409. unit_unfill[block->unit_hash]->samesize_no > block->samesize_no
  410. ) {
  411. unit_unfill[block->unit_hash] = block;
  412. }
  413. }
  414. ptr = NULL;
  415. }
  416. }
  417. }
  418. /* 現在の状況を表示する */
  419. static void memmgr_info(void) {
  420. int i;
  421. struct block *p;
  422. ShowInfo("** Memory Manager Information **\n");
  423. if(block_first == NULL) {
  424. ShowMessage("Uninitialized.\n");
  425. return;
  426. }
  427. ShowMessage(
  428. "Blocks: %04u , BlockSize: %06u Byte , Used: %08uKB\n",
  429. block_last->block_no+1,sizeof(struct block),
  430. (block_last->block_no+1) * sizeof(struct block) / 1024
  431. );
  432. p = block_first;
  433. for(i=0;i<=block_last->block_no;i++) {
  434. ShowMessage(" Block #%04u : ",p->block_no);
  435. if(p->unit_size == 0) {
  436. ShowMessage("unused.\n");
  437. } else {
  438. ShowMessage(
  439. "size: %05u byte. used: %04u/%04u prev:",
  440. p->unit_size - sizeof(struct unit_head),p->unit_used,p->unit_count
  441. );
  442. if(p->samesize_prev == NULL) {
  443. ShowMessage("NULL");
  444. } else {
  445. ShowMessage("%04u",(p->samesize_prev)->block_no);
  446. }
  447. ShowMessage(" next:");
  448. if(p->samesize_next == NULL) {
  449. ShowMessage("NULL");
  450. } else {
  451. ShowMessage("%04u",(p->samesize_next)->block_no);
  452. }
  453. ShowMessage("\n");
  454. }
  455. p = p->block_next;
  456. }
  457. }
  458. /* ブロックを確保する */
  459. static struct block* block_malloc(void) {
  460. if(block_unused != NULL) {
  461. /* ブロック用の領域は確保済み */
  462. struct block* ret = block_unused;
  463. do {
  464. block_unused = block_unused->block_next;
  465. } while(block_unused != NULL && block_unused->unit_size != 0);
  466. return ret;
  467. } else {
  468. /* ブロック用の領域を新たに確保する */
  469. int i;
  470. int block_no;
  471. struct block* p;
  472. struct chunk* chunk;
  473. char *pb = (char *) CALLOC (sizeof(struct block),BLOCK_ALLOC + 1);
  474. if(pb == NULL) {
  475. ShowFatalError("Memory manager::block_alloc failed.\n");
  476. exit(1);
  477. }
  478. // store original block address in chunk
  479. chunk = (struct chunk *) MALLOC (sizeof(struct chunk));
  480. if (chunk == NULL) {
  481. ShowFatalError("Memory manager::block_alloc failed.\n");
  482. exit(1);
  483. }
  484. chunk->block = pb;
  485. chunk->next = (chunk_first) ? chunk_first : NULL;
  486. chunk_first = chunk;
  487. // ブロックのポインタの先頭をsizeof(block) アライメントに揃える
  488. // このアドレスをfree() することはないので、直接ポインタを変更している。
  489. pb += sizeof(struct block) - ((unsigned long)pb % sizeof(struct block));
  490. p = (struct block*)pb;
  491. if(block_first == NULL) {
  492. /* 初回確保 */
  493. block_no = 0;
  494. block_first = p;
  495. } else {
  496. block_no = block_last->block_no + 1;
  497. block_last->block_next = p;
  498. p->block_prev = block_last;
  499. }
  500. block_last = &p[BLOCK_ALLOC - 1];
  501. /* ブロックを連結させる */
  502. for(i=0;i<BLOCK_ALLOC;i++) {
  503. if(i != 0) {
  504. p[i].block_prev = &p[i-1];
  505. }
  506. if(i != BLOCK_ALLOC -1) {
  507. p[i].block_next = &p[i+1];
  508. }
  509. p[i].block_no = block_no + i;
  510. }
  511. /* 未使用ブロックへのポインタを更新 */
  512. block_unused = &p[1];
  513. p->unit_size = 1;
  514. return p;
  515. }
  516. }
  517. static void block_free(struct block* p) {
  518. /* free() せずに、未使用フラグを付けるだけ */
  519. p->unit_size = 0;
  520. /* 未使用ポインターを更新する */
  521. if(block_unused == NULL) {
  522. block_unused = p;
  523. } else if(block_unused->block_no > p->block_no) {
  524. block_unused = p;
  525. }
  526. }
  527. unsigned int memmgr_usage (void)
  528. {
  529. return memmgr_usage_bytes / 1024;
  530. }
  531. #ifdef LOG_MEMMGR
  532. static char memmer_logfile[128];
  533. static FILE *log_fp;
  534. static void memmgr_log (char *buf)
  535. {
  536. if (!log_fp) {
  537. log_fp = fopen(memmer_logfile,"w");
  538. if (!log_fp) log_fp = stdout;
  539. fprintf(log_fp, "Memory manager: Memory leaks found (Revision %s).\n", get_svn_revision());
  540. }
  541. fprintf(log_fp, buf);
  542. return;
  543. }
  544. #endif
  545. static void memmgr_final (void)
  546. {
  547. struct block *block = block_first;
  548. struct chunk *chunk = chunk_first, *chunk2;
  549. struct unit_head_large *large = unit_head_large_first, *large2;
  550. int i;
  551. #ifdef LOG_MEMMGR
  552. int count = 0;
  553. char buf[128];
  554. #endif
  555. while (block) {
  556. if (block->unit_size) {
  557. for (i = 0; i < block->unit_count; i++) {
  558. struct unit_head *head = (struct unit_head*)(&block->data[block->unit_size * i]);
  559. if(head->block != NULL)
  560. {
  561. #ifdef LOG_MEMMGR
  562. sprintf (buf,
  563. "%04d : %s line %d size %d\n", ++count,
  564. head->file, head->line, head->size);
  565. memmgr_log (buf);
  566. #endif
  567. // get block pointer and free it [celest]
  568. _mfree ((char *)head + sizeof(struct unit_head) - sizeof(int), ALC_MARK);
  569. }
  570. }
  571. }
  572. //if (block->block_no >= block2->block_no + BLOCK_ALLOC - 1) {
  573. // reached a new block array
  574. //block = block->block_next;
  575. /* Okay wise guys... this is how block2 was allocated: [Skotlex]
  576. struct block* p;
  577. char *pb = (char *) CALLOC (sizeof(struct block),BLOCK_ALLOC + 1);
  578. pb += sizeof(struct block) - ((unsigned long)pb % sizeof(struct block));
  579. p = (struct block*)pb;
  580. The reason we get an invalid pointer is that we allocated pb, not p.
  581. So how do you get pb when you only have p?
  582. The answer is, you can't, because the original pointer was lost when
  583. memory-aligning the block. So we either forget this FREE or use a
  584. self-reference...
  585. Since we are already quitting, it might be ok to just not free the block
  586. as it is.
  587. */
  588. // didn't realise that before o.o -- block chunks are now freed below [celest]
  589. // FREE(block2);
  590. //block2 = block;
  591. //continue;
  592. //}
  593. block = block->block_next;
  594. }
  595. // free the allocated block chunks
  596. chunk = chunk_first;
  597. while (chunk) {
  598. chunk2 = chunk->next;
  599. FREE(chunk->block);
  600. FREE(chunk);
  601. chunk = chunk2;
  602. }
  603. while(large) {
  604. large2 = large->next;
  605. #ifdef LOG_MEMMGR
  606. sprintf (buf,
  607. "%04d : %s line %d size %d\n", ++count,
  608. large->unit_head.file, large->unit_head.line, large->unit_head.size);
  609. memmgr_log (buf);
  610. #endif
  611. FREE (large);
  612. large = large2;
  613. }
  614. #ifdef LOG_MEMMGR
  615. if(count == 0) {
  616. ShowInfo("Memory manager: No memory leaks found.\n");
  617. } else {
  618. ShowWarning("Memory manager: Memory leaks found and fixed.\n");
  619. fclose(log_fp);
  620. }
  621. #endif
  622. return;
  623. }
  624. static void memmgr_init (void)
  625. {
  626. #ifdef LOG_MEMMGR
  627. sprintf(memmer_logfile, "log/%s.leaks", SERVER_NAME);
  628. ShowStatus("Memory manager initialised: "CL_WHITE"%s"CL_RESET"\n", memmer_logfile);
  629. #endif
  630. return;
  631. }
  632. #endif
  633. #if defined(MEMSET_TURBO) && defined(_WIN32)
  634. void malloc_set(void *dest, int value, int count){
  635. _asm
  636. {
  637. mov eax, value
  638. mov ecx, count
  639. mov ebx, ecx
  640. mov edi, dest
  641. shr ecx, 2
  642. test ecx, ecx
  643. jz ByteOp
  644. shl ecx, 2
  645. sub ebx, ecx
  646. shr ecx, 2
  647. rep stosd
  648. test ebx, ebx
  649. jz Done
  650. ByteOp:
  651. mov ecx, ebx
  652. rep stosb
  653. Done:
  654. }
  655. }
  656. // Sets 32-bit aligned memory.
  657. void malloc_tsetdword(void *dest, int value, int count){
  658. _asm
  659. {
  660. mov edi, dest
  661. mov ecx, count
  662. shr ecx, 2
  663. mov eax, value
  664. rep stosd
  665. }
  666. }
  667. // Sets 16-bit aligned memory.
  668. void malloc_tsetword(void *dest, short value, int count){
  669. _asm
  670. {
  671. mov edi, dest
  672. mov ecx, count
  673. shr ecx, 1
  674. mov ax, value
  675. rep stosw
  676. }
  677. }
  678. #endif
  679. /*======================================
  680. * Initialise
  681. *--------------------------------------
  682. */
  683. unsigned int malloc_usage (void)
  684. {
  685. #ifdef USE_MEMMGR
  686. return memmgr_usage ();
  687. #else
  688. return 0;
  689. #endif
  690. }
  691. void malloc_final (void)
  692. {
  693. #ifdef USE_MEMMGR
  694. memmgr_final ();
  695. #endif
  696. return;
  697. }
  698. void malloc_init (void)
  699. {
  700. #ifdef USE_MEMMGR
  701. memmgr_init ();
  702. #endif
  703. return;
  704. }