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 */
|
Let a fool hold his tongue and he will pass for a sage. |