広告
Linux Kernelのリスト構造を参考に作成。
環境:CentOS 6, gcc version 4.4.7
mempool.h
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 |
#ifndef _MEMPOOL_H_ #define _MEMPOOL_H_ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <stdint.h> #include <stddef.h> #define EASY_ELECTORIC_FENCE (0x123456789) #define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next) #define GET_ENTRY(ptr,type,member) \ ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) #define Malloc(size) \ __Malloc(size, __FILE__, __LINE__) #define Free(ptr) \ __Free(ptr) struct mem_list { struct mem_list *prev; struct mem_list *next; }; typedef struct { struct mem_list head; int32_t entry_count; } MemListHead_t; typedef struct { struct mem_list list; int64_t fence; /* electoric fence */ char file[64]; /* ファイル名 */ int32_t line; /* 行数 */ struct timeval tv; /* 取得時刻 */ int32_t size; /* memory size */ void* address; /* dataのアドレス */ uint8_t data[0]; /* ユーザに渡すポインタ */ } MemListEntry_t; static inline memlist_init( struct mem_list *head) { head->prev = head; head->next = head; } static inline memlist_add_tail( struct mem_list *entry, struct mem_list *head) { head->prev->next = entry; entry->next = head; entry->prev = head->prev; head->prev = entry; } static inline memlist_del( struct mem_list *entry, struct mem_list *head) { entry->prev->next = entry->next; entry->next->prev = entry->prev; entry->next = (struct mem_list *)0xdeaddead; entry->prev = (struct mem_list *)0xdeaddead; } extern void* __Malloc(size_t size, char* file, size_t line); extern void __Free(void* ptr); #endif /* _MEMPOOL_H_ */ |
mempool.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 |
#include "mempool.h" extern MemListHead_t MngMem; void* __Malloc( size_t size, char* file, size_t line) { void* ptr = NULL; MemListEntry_t* entry = (MemListEntry_t*) malloc(sizeof(*entry)+size); if (NULL != entry) { entry->fence = EASY_ELECTORIC_FENCE; entry->size = size; snprintf(entry->file, sizeof(entry->file)-1, "%s", file); entry->line = line; gettimeofday(&entry->tv, NULL); entry->address = &entry->data[0]; memlist_add_tail(&entry->list, &MngMem.head); ptr = &entry->data[0]; } return ptr; } void __Free( void* ptr) { MemListEntry_t* entry = (MemListEntry_t*)((uint8_t*)ptr - sizeof(MemListEntry_t)); if(!(entry->address == ptr && EASY_ELECTORIC_FENCE != entry->fence)) { /* memory currupted or invalid address */ } memlist_del(&entry->list, &MngMem.head); free(entry); } |
memtest.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 |
#include "mempool.h" MemListHead_t MngMem; typedef struct { int a; int b; int c; int d; int e[1024]; } testData_t; int main(int argc, char *argv[]) { /* メモリ管理リスト初期化 */ memlist_init(&MngMem.head); /* メモリ領域を確保 */ testData_t *dat1 = (testData_t* )Malloc(sizeof(*dat1)); testData_t *dat2 = (testData_t* )Malloc(sizeof(*dat2)+1); testData_t *dat3 = (testData_t* )Malloc(sizeof(*dat3)+2); /* dat1,2,3がメモリ管理リストに追加されているか確認 */ struct mem_list *p; printf("##### BEFORE #####\n"); printf("file:line, size, fence, address\n"); printf("-------------------------------\n"); list_for_each(p, &(MngMem.head)) { MemListEntry_t *gp = GET_ENTRY(p, MemListEntry_t, list); printf("%s:%u, %d, %#llx, %p\n", gp->file, gp->line, gp->size, gp->fence, gp->address); } /* dat2の削除 */ Free(dat2); /* メモリ管理リストからdat2のエントリが消えているか確認 */ printf("##### AFTER1 #####\n"); printf("file:line, size, fence, address\n"); printf("-------------------------------\n"); list_for_each(p, &(MngMem.head)) { MemListEntry_t *gp = GET_ENTRY(p, MemListEntry_t, list); printf("%s:%u, %d, %#llx, %p\n", gp->file, gp->line, gp->size, gp->fence, gp->address); } /* dat1, dat3の削除 */ Free(dat1); Free(dat3); /* メモリ管理リストからエントリがすべて消えているか確認 */ printf("##### AFTER2 #####\n"); printf("file:line, size, fence, address\n"); printf("-------------------------------\n"); list_for_each(p, &(MngMem.head)) { MemListEntry_t *gp = GET_ENTRY(p, MemListEntry_t, list); printf("%s:%u, %d, %#llx, %p\n", gp->file, gp->line, gp->size, gp->fence, gp->address); } return 0; } |
Makefile
1 2 3 4 5 6 7 8 9 10 11 |
memtest: memtest.o mempool.o gcc -g -o memtest memtest.o mempool.o memtest.o: memtest.c mempool.h gcc -g -c memtest.c mempool.o: mempool.c mempool.h gcc -g -c mempool.c clean: *.o rm -f *.o |
動作確認
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
$ make gcc -g -c memtest.c gcc -g -c mempool.c gcc -g -o memtest memtest.o mempool.o $ $ ./memtest ##### BEFORE ##### file:line, size, fence, address ------------------------------- memtest.c:18, 4112, 0x123456789, 0x6b7090 memtest.c:20, 4113, 0x123456789, 0x6b8130 memtest.c:22, 4114, 0x123456789, 0x6b91d0 ##### AFTER1 ##### file:line, size, fence, address ------------------------------- memtest.c:18, 4112, 0x123456789, 0x6b7090 memtest.c:22, 4114, 0x123456789, 0x6b91d0 ##### AFTER2 ##### file:line, size, fence, address ------------------------------- |
広告
広告