xmalloc
TODO: ¾ÆÁ÷ ¿ÏÀüÈ÷ ¾´ ¹®¼´Â ¾Æ´Õ´Ï´Ù. ¼öÁ¤Çϱâ Àü¿¡ CCodeSnippets¸¦ Àоî Áֽñ⠹ٶø´Ï´Ù.
TODO: ...
ÀϹÝÀûÀ¸·Î, ¹ö±×¸¦ ¹ß»ýÇÒ È®·üÀÌ °¡Àå ³ôÀº °÷Àº, malloc(3), calloc(3), realloc(3), ¶Ç´Â free(3)¸¦ ½á¼ ¸Þ¸ð¸®¸¦ µ¿ÀûÀ¸·Î ¾ò°í µ¹·ÁÁÖ´Â ºÎºÐÀÔ´Ï´Ù. ´ÙÀ½°ú °°Àº Ãæ°í¸¦ ±â¾ïÇÏ°í ÀÖÀ¸¸é ¹ö±× ¹ß»ý È®·üÀ» Á¶±ÝÀ̳ª¸¶ ÁÙÀÏ ¼ö ÀÖ½À´Ï´Ù:
TODO: efence µî ¼Ò°³
ÀÌ Àý¿¡¼ ´Ù·ê xmallocÀº malloc()/calloc()/realloc()/free()¿¡ ±â´ÉÀ» Á¶±Ý Ãß°¡ÇÏ¿©, ³ªÁß¿¡ µð¹ö±ë ¶Ç´Â ¼º´ÉÀ» °³¼±ÇÏ·Á ÇÒ ¶§ µµ¿òÀ» ÁÙ ¼ö ÀÖ´Â ¸ðµâÀÔ´Ï´Ù.
TODO: µ¥½ºÆ®Å¾ ȯ°æ¿¡¼´Â °ÅÀÇ ÇÊ¿ä¾ø´Ù´Â °ÍÀ» ¾Ë¸²...
¿ø·¡ ÀÌ ¸ðµâÀº Linux ½Ã½ºÅÛ¿¡¼ ¾²·Á°í ¸¸µç °ÍÀÌ ¾Æ´Õ´Ï´Ù. Embedded device¿Í °°ÀÌ Á¦°øµÇ´Â C ¶óÀ̺귯¸®°¡ »ó´ëÀûÀ¸·Î ÁÁÀº µð¹ö±ë ȯ°æÀ» °®Ã߱Ⱑ ¾î·Æ±â ¶§¹®¿¡ µðÀÚÀÎÇÑ °ÍÀÔ´Ï´Ù.
DeleteMe: calloc() Àº ÇÒ´çÇÏ´Â memory ¸¦ 0 À¸·Î ÃʱâÈÇÕ´Ï´Ù. xcalloc() µµ ÃʱâÈ·çƾÀÌ ÇÊ¿äÇÏÁö ¾ÊÀ»±î¿ä?
DeleteMe: header ÀÇ redzone °ú footer ÀÇ redzone Àº ±× ¿ªÇÒÀÌ µ¿ÀÏÇÑ °ÍÀ¸·Î º¸À̴µ¥ xfree() ÇÔ¼ö¿¡¼ ±»ÀÌ µÎ redzone ÀÇ ¿À·ù󸮹æ½ÄÀÌ ´Ù¸¥ ÀÌÀ¯°¡ ÀÖ½À´Ï±î?
...
xmalloc ¸ðµâÀÌ Á¦°øÇÏ´Â °¡Àå ´ëÇ¥ÀûÀÎ ÇÔ¼ö´Â ´ÙÀ½°ú °°½À´Ï´Ù:
void *xmalloc(size_t size);
void *xcalloc(size_t nmemb, size_t size); void *xrealloc(void *ptr, size_t size); void xfree(void *ptr);
struct xmemheader {
size_t size; unsigned int redzone; }; struct xmemfooter { unsigned int redzone[2]; };
static int malloc_called;
static int calloc_called; static int realloc_called; static int free_called;
static long xmem_limit = -1;
static size_t xmem_cur_size; static size_t xmem_max_size;
static FILE *xmem_error_stream = stderr;
static void (*xalloc_failed_handler)(void) = abort; xmalloc() ¶¾Æ·¡´Â xmalloc()ÀÇ ½ÇÁ¦ ÄÚµåÀÔ´Ï´Ù. ¸î °¡Áö ¾ÆÁ÷ ¼³¸íÇÏÁö ¾ÊÀº ºÎºÐÀÌ ÀÖÁö¸¸, ¸ÕÀú xmalloc()ÀÌ ¾î¶² ½ÄÀ¸·Î µ¿ÀÛÇÏ´ÂÁö ¾Ë¾ÆµÓ½Ã´Ù:
void *
xmalloc(size_t size) { void *ptr; if (size == 0) size = 1; ptr = malloc(ptr_size(size)); if (!ptr || add_stat(size) < 0) goto err; malloc_called++; return set_ptr(ptr, size); err: if (xalloc_failed_handler) xalloc_failed_handler(); return 0; }
static __inline__ size_t
ptr_size(size_t size) { size += sizeof(struct xmemheader); size += sizeof(struct xmemfooter); return size; }
static __inline__ void *
set_ptr(void *ptr, size_t size) { struct xmemheader head; head.redzone = XMEM_HEADER; head.size = size; memcpy(ptr, &head, sizeof(head)); static struct xmemfooter foot = { { XMEM_FOOTER, XMEM_FOOTER } }; memcpy((char *)ptr + sizeof(head) + size, &foot, sizeof(foot)); return (char *)ptr + sizeof(head); }
static __inline__ int
add_stat(size_t size) { if (xmem_limit > 0 && xmem_cur_size + size > xmem_limit) return -1; xmem_cur_size += size; if (xmem_max_size < xmem_cur_size) xmem_max_size = xmem_cur_size; return 0; } xcalloc() ¶xmalloc()°ú´Â ´Þ¸®, xcalloc()Àº calloc(3)À» ºÎ¸£Áö ¾Ê°í, malloc()À» ºÒ·¯¼ calloc(3)ÀÇ ¿ªÇÒÀ» ÇÕ´Ï´Ù. ¾Õ¿¡¼ ¼³¸íÇÑ xmalloc()À» ´Ù ÀÌÇØÇß°í, calloc(3)À» ¾Ë°í ÀÖ´Ù¸é ¾Æ·¡ ¼Ò½º¸¦ ÆľÇÇϴµ¥ Å« ¾î·Á¿òÀº ¾ø½À´Ï´Ù.
void *
xcalloc(size_t nmemb, size_t size) { void *ptr; size = size * nmemb; if (size == 0) size = 1; ptr = malloc(ptr_size(size)); if (!ptr || add_stat(size) < 0) goto err; calloc_called++; return set_ptr(ptr, size); err: if (xalloc_failed_handler) xalloc_failed_handler(); return 0; } xrealloc() ¶¾Æ·¡´Â xrealloc()ÀÇ ¼Ò½ºÀÔ´Ï´Ù. ¸¶Âù°¡Áö·Î Å©°Ô ¾î·ÆÁö ¾Ê½À´Ï´Ù.
void *
xrealloc(void *ptr, size_t size) { if (size == 0) size = 1; ptr = get_ptr(ptr); ptr = realloc(ptr, ptr_size(size)); if (!ptr || add_stat(size) < 0) goto err; realloc_called++; return set_ptr(ptr, size); err: if (xalloc_failed_handler) xalloc_failed_handler(); return 0; } xfree() ¶free()ÀÇ °æ¿ì, ¾Õ¿¡¼ ¼³¸íÇÑ, ¸Þ¸ð¸®¸¦ ÇÒ´çÇÏ´Â ÇÔ¼öµé°ú´Â ´Þ¸®, Á» ´Ù¸¥ ÀÛ¾÷À» ¸ÕÀú ÇØ¾ß ÇÕ´Ï´Ù. Figure 3.1¿¡¼ ¼³¸íÇÑ redzoneÀÌ, ¿ø·¡ ¼³Á¤Çß´ø °ªÀ¸·Î Á¦´ë·Î ¼³Á¤µÇ¾î ÀÖ´ÂÁö, ...
xmalloc.h ¶
/* $Id: xmalloc,v 1.6 2005/03/22 06:10:28 kss Exp kss $ */
/* * malloc debugger * Copyright (C) 2004 Seong-Kook Shin <cinsk.shin at samsung.com> */ #ifndef XMALLOC_H_ #define XMALLOC_H_ #ifdef HAVE_CONFIG_H # include <config.h> #endif #include <stddef.h> /* This indirect using of extern "C" { ... } makes Emacs happy */ #ifndef BEGIN_C_DECLS # ifdef __cplusplus # define BEGIN_C_DECLS extern "C" { # define END_C_DECLS } # else # define BEGIN_C_DECLS # define END_C_DECLS # endif #endif /* BEGIN_C_DECLS */ BEGIN_C_DECLS #define XMEM_STAT #define XMEM_REDZONE #ifndef NDEBUG extern void *xmalloc(size_t size); extern void *xcalloc(size_t nmemb, size_t size); extern void *xrealloc(void *ptr, size_t size); extern void xfree(void *ptr); extern void xmemstat(memstat_t *ms); extern long xmemopt(int option, ...); #else # define xmalloc(size) malloc(size) # define xcalloc(nmemb, size) calloc(nmemb, size) # define xrealloc(ptr, size) realloc(ptr, size) # define xfree(ptr) free(ptr) # define xmemstat(ms) ((void)0) # define xmemopt(opt, val) ((long)-1) #endif /* NDEBUG */ struct memstat_ { int malloc_called; int calloc_called; int realloc_called; int free_called; size_t cur_size; size_t max_size; ssize_t limit; }; typedef struct memstat_ memstat_t; enum { X_SETLIM, /* Set memory limit */ X_GETLIM, /* Get memory limit */ X_SETFH, /* Set the failed handler */ X_GETFH, /* Get the failed handler */ X_SETES, /* Set the error stream */ X_GETES, /* Get the error stream */ }; END_C_DECLS #endif /* XMALLOC_H_ */ xmalloc.c ¶
/* $Id: xmalloc,v 1.6 2005/03/22 06:10:28 kss Exp kss $ */
/* * malloc debugger * Copyright (C) 2004 Seong-Kook Shin <cinsk.shin at samsung.com> */ #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <xmalloc.h> static long xmem_limit = -1; static int malloc_called; static int calloc_called; static int realloc_called; static int free_called; static size_t xmem_cur_size; static size_t xmem_max_size; static FILE *xmem_error_stream = stderr; static void (*xalloc_failed_handler)(void) = abort; #define XMEM_HEADER ((0x2B2B56 << 16) + 0x1F6781) #define XMEM_FOOTER 0xdeadbeef struct xmemheader { size_t size; unsigned int redzone; }; struct xmemfooter { unsigned int redzone[2]; }; static __inline__ size_t ptr_size(size_t size) { #ifdef XMEM_STAT size += sizeof(struct xmemheader); #endif #ifdef XMEM_REDZONE size += sizeof(struct xmemfooter); #endif return size; } static __inline__ void * set_ptr(void *ptr, size_t size) { #ifdef XMEM_STAT struct xmemheader head; head.redzone = XMEM_HEADER; head.size = size; memcpy(ptr, &head, sizeof(head)); #endif #ifdef XMEM_REDZONE { static struct xmemfooter foot = { { XMEM_FOOTER, XMEM_FOOTER } }; memcpy((char *)ptr + sizeof(head) + size, &foot, sizeof(foot)); } #endif #ifdef XMEM_STAT return (char *)ptr + sizeof(head); #else return ptr; #endif /* XMEM_STAT */ } static __inline__ void * get_ptr(void *ptr) { #ifdef XMEM_STAT return (char *)ptr - sizeof(struct xmemheader); #else return (char *)ptr; #endif } static __inline__ int add_stat(size_t size) { if (xmem_limit > 0 && xmem_cur_size + size > xmem_limit) return -1; xmem_cur_size += size; if (xmem_max_size < xmem_cur_size) xmem_max_size = xmem_cur_size; return 0; } void * xmalloc(size_t size) { void *ptr; if (size == 0) size = 1; ptr = malloc(ptr_size(size)); if (!ptr || add_stat(size) < 0) goto err; malloc_called++; return set_ptr(ptr, size); err: if (xalloc_failed_handler) xalloc_failed_handler(); return 0; } void * xcalloc(size_t nmemb, size_t size) { void *ptr; size = size * nmemb; if (size == 0) size = 1; ptr = malloc(ptr_size(size)); if (!ptr || add_stat(size) < 0) goto err; calloc_called++; return set_ptr(ptr, size); err: if (xalloc_failed_handler) xalloc_failed_handler(); return 0; } void * xrealloc(void *ptr, size_t size) { if (size == 0) size = 1; ptr = get_ptr(ptr); ptr = realloc(ptr, ptr_size(size)); if (!ptr || add_stat(size) < 0) goto err; realloc_called++; return set_ptr(ptr, size); err: if (xalloc_failed_handler) xalloc_failed_handler(); return 0; } static __inline__ int redzone_check(void *ptr, size_t size) { #ifdef XMEM_REDZONE int i = 0; struct xmemfooter *p = (struct xmemfooter *)((char *)ptr + sizeof(struct xmemheader) + size); while (i < sizeof(p->redzone) / sizeof(int)) { if (p->redzone[i] != XMEM_FOOTER) return -1; i++; } #endif /* XMEM_REDZONE */ return 0; } void xfree(void *ptr) { #ifdef XMEM_STAT { struct xmemheader *p; p = (struct xmemheader *)get_ptr(ptr); if (p->redzone != XMEM_HEADER) { /* Invalid usage of xfree(), PTR wasn't generated by xmalloc() */ if (xmem_error_stream) fprintf(xmem_error_stream, "error: xfree() failed: redzone is not valid\n"); return; } xmem_cur_size -= p->size; if (redzone_check(p, p->size) < 0 && xalloc_failed_handler) xalloc_failed_handler(); } #endif free_called++; free(get_ptr(ptr)); } long xmemopt(int option, ...) { va_list ap; switch (option) { #ifdef XMEM_STAT case X_SETLIM: va_start(ap, option); xmem_limit = va_arg(ap, long); va_end(ap); break; case X_GETLIM: return xmem_limit; #endif /* XMEM_STAT */ case X_SETES: va_start(ap, option); xmem_error_stream = va_arg(ap, FILE *); va_end(ap); break; case X_GETES: return (long)xmem_error_stream; case X_SETFH: va_start(ap, option); xalloc_failed_handler = va_arg(ap, void (*)(void)); va_end(ap); break; case X_GETFH: return (long)xalloc_failed_handler; default: return -1; } return 0; } void xmemstat(memstat_t *ms) { ms->malloc_called = malloc_called; ms->calloc_called = calloc_called; ms->realloc_called = realloc_called; ms->free_called = free_called; ms->cur_size = xmem_cur_size; ms->max_size = xmem_max_size; ms->limit = xmem_limit; } #ifdef TEST_XMALLOC #include <stdio.h> int main(void) { memstat_t ms; char *vec[80]; int i, j; xmemopt(X_SETLIM, 10000); xmemopt(X_SETFH, abort); for (i = 0; i < 80; i++) { int size = rand() % 1000; printf("xmalloc(%d) called..\n", size); vec[i] = xmalloc(size); for (j = 0; j < size; j++) { vec[i][j] = '*'; } } for (i = 0; i < 60; i++) { int size = rand() % 1000; printf("xrealloc(0x%08X, %d) called..\n", (int)vec[i], size); vec[i] = xrealloc(vec[i], size); for (j = 0; j < size; j++) { vec[i][j] = '*'; } } for (i = 0; i < 80; i++) { xfree(vec[i]); } xmemstat(&ms); return 0; } #endif /* TEST_XMALLOC */ |
Many pages make a thick book. |