· KLDP.org · KLDP.net · KLDP Wiki · KLDP BBS ·
xmalloc

TODO: ¾ÆÁ÷ ¿ÏÀüÈ÷ ¾´ ¹®¼­´Â ¾Æ´Õ´Ï´Ù. ¼öÁ¤Çϱâ Àü¿¡ CCodeSnippets¸¦ Àоî Áֽñ⠹ٶø´Ï´Ù.

TODO: ...


ÀϹÝÀûÀ¸·Î, ¹ö±×¸¦ ¹ß»ýÇÒ È®·üÀÌ °¡Àå ³ôÀº °÷Àº, malloc(3), calloc(3), realloc(3), ¶Ç´Â free(3)¸¦ ½á¼­ ¸Þ¸ð¸®¸¦ µ¿ÀûÀ¸·Î ¾ò°í µ¹·ÁÁÖ´Â ºÎºÐÀÔ´Ï´Ù. ´ÙÀ½°ú °°Àº Ãæ°í¸¦ ±â¾ïÇÏ°í ÀÖÀ¸¸é ¹ö±× ¹ß»ý È®·üÀ» Á¶±ÝÀ̳ª¸¶ ÁÙÀÏ ¼ö ÀÖ½À´Ï´Ù:
  • malloc(3)/calloc(3)/realloc(3)À¸·Î ¾òÀº ¸Þ¸ð¸®´Â ¹Ýµå½Ã free(3)¸¦ ºÒ·¯¼­ µ¹·ÁÁØ´Ù.
  • malloc(3)/calloc(3)/realloc(3)À» ºÎ¸¥ ÈÄ, ¹Ýµå½Ã ¸®ÅÏ °ªÀÌ ³ÎÀÎÁö °Ë»çÇÑ´Ù.
  • free(3)¸¦ ºÎ¸¥ ´ÙÀ½, µ¹·ÁÁØ ¸Þ¸ð¸®´Â Àаųª ¾²Áö ¾Ê´Â´Ù.
  • ÀÌ¹Ì free(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);
°¢°¢ÀÇ ÇÔ¼ö°¡ ÇÏ´Â ÀÏÀº malloc(3), calloc(3), realloc(3), free(3)ÀÌ ÇÏ´Â ÀÏ°ú °°À¸¸ç, ´ÙÀ½°ú °°Àº ±â´ÉÀ» Ãß°¡ÀûÀ¸·Î Á¦°øÇÕ´Ï´Ù.
  1. malloc()¿¡ Å©±â¸¦ 0À¸·Î ÁÖ¾úÀ» ¶§ÀÇ ¹®Á¦¸¦ ÇØ°áÇÑ´Ù.
  2. °¢°¢ÀÇ ÇÔ¼öµéÀÌ ¸î ¹ø¾¿ ºÒ·È´ÂÁö ±× Ƚ¼ö¸¦ Á¦°øÇÑ´Ù.
  3. Á¦ÇÑ Å©±â¸¦ µÎ°í, ÀÌ Å©±â¸¦ ³ÑÀ¸¸é ¸Þ¸ð¸®°¡ ºÎÁ·ÇÑ °Íó·³ Èä³»³½´Ù.
  4. µ¿ÀûÀ¸·Î ÇÒ´çµÈ ¸Þ¸ð¸®ÀÇ Å©±â¸¦ Á¦°øÇÑ´Ù.
  5. µ¿ÀûÀ¸·Î ÇÒ´ç¹ÞÀº ¸Þ¸ð¸® Å©±â¿¡ ¹þ¾î³ª´Â Á¢±Ù(read/write)¸¦ ¿¹¹æÇÑ´Ù.
óÀ½ ±â´ÉÀº ¸Å¿ì °£´ÜÇÕ´Ï´Ù. ÀÎÀÚ°¡ 0À¸·Î µé¾î¿À¸é 1·Î ¹Ù²Ù¸é µË´Ï´Ù. µÎ ¹ø° ±â´ÉÀº Àü¿ª º¯¼ö¸¦ ¸î °³ µÎ¸é °£´ÜÈ÷ ÇØ°áµË´Ï´Ù. Áï °¢°¢ÀÇ ÇÔ¼ö°¡ ºÒ·ÁÁ³À» ¶§, ÇØ´çÇÏ´Â Àü¿ª º¯¼öÀÇ °ªÀ» Çϳª¾¿ Áõ°¡½ÃÅ°¸é, ³ªÁß¿¡ ¸î ¹ø¾¿ ºÒ·È´ÂÁö ½±°Ô ¾Ë ¼ö ÀÖ½À´Ï´Ù. ¼¼¹ø° ±â´Éµµ ¸¶Âù°¡Áö·Î, Á¦ÇÑ Å©±â¸¦ ¾î¶² Àü¿ª º¯¼ö¿¡ ÀúÀåÇØ µÎ°í, ¸Þ¸ð¸®¸¦ ÇÒ´çÇϱâ Àü¿¡ üũÇÏ¸é µË´Ï´Ù. ³×¹ø° ±â´ÉÀº ²Ï ±î´Ù·Ó½À´Ï´Ù. ÀÏ´Ü malloc(3)À» Á÷Á¢ ¸¸µéÁö ¾Ê´ÂÇÑ, µ¿ÀûÀ¸·Î ¾òÀº ¾î¶² ¸Þ¸ð¸® ºí·°ÀÇ Å©±â¸¦ ¾Ë¾Æ³»´Â °ÍÀº ºÒ°¡´ÉÇÕ´Ï´Ù. µû¶ó¼­ malloc(3)À¸·Î ºí·°À» ¾òÀ» ¶§, ½ÇÁ¦ ÇÊ¿äÇÑ °ø°£º¸´Ù Á¶±Ý ´õ ¾ò¾î³½ ´ÙÀ½, ±× Ãß°¡ ºÎºÐ¿¡ ÀÌ ºí·°À» ¿äûÇÒ ¶§ÀÇ Å©±â¸¦ ±â·ÏÇØ µÎ´Â ¹æ½ÄÀ» ¾²°Ú½À´Ï´Ù. ¹°·Ð ÀÌ·±½ÄÀ¸·Î ÇØ°áÇϸé, »ó´çÈ÷ ¸¹Àº ¿À¹öÇìµå°¡ ¿¹»óµÇÁö¸¸, ¾îÂ÷ÇÇ ÀÌ ¸ðµâÀº µð¹ö±ëÀ» À§ÇÑ °ÍÀ̱⠶§¹®¿¡ ±¦Âú½À´Ï´Ù. ´Ù¼¸¹ø° ±â´ÉÀ», ½Ã½ºÅÛ¿¡ µ¶¸³ÀûÀÎ ÄÚµå·Î ¿ÏÀüÈ÷ ÇØ°áÇϱâ¶õ »ç½Ç»ó ºÒ°¡´ÉÇÕ´Ï´Ù. Xmalloc ¸ðµâ¿¡¼­´Â, ¿ä±¸ÇÑ ºí·°ÀÇ ¾Õ µÚ ºÎºÐ¿¡ ƯÁ¤ °ªÀ» °¡Áø Ãß°¡ÀûÀÎ ºí·°À» ÇÒ´çÇÏ°í, ³ªÁß¿¡ ÀÌ ºí·°À» µÇµ¹·Á ÁÙ ¶§, ÀÌ ºí·°ÀÇ °ªÀÌ º¯°æµÇ¾ú´ÂÁö °Ë»çÇÏ´Â ¹æ¹ýÀ¸·Î ÀÌ ¹®Á¦¸¦ ÇØ°áÇÕ´Ï´Ù. ÆíÀÇ»ó ÀÌ Ãß°¡ÀûÀÎ ºí·°À» ¡®redzone¡¯À̶ó°í ºÎ¸£±â·Î ÇÕ´Ï´Ù. Figure 3.1¸¦ º¸¸é xmalloc()ÀÌ ½ÇÁ¦ malloc(3)¿¡°Ô ¿ä±¸ÇÏ´Â ºí·°ÀÇ Å©±â´Â »ç¿ëÀÚ°¡ ¿ä±¸ÇÑ ºí·°(¡®requested block¡¯)º¸´Ù Å« °ÍÀ» ¾Ë ¼ö ÀÖÀ¸¸ç, ÀÌ ¿©ºÐÀÇ °ø°£ÀÌ ¾î¶² ¸ñÀûÀ¸·Î ¾²ÀÌ´ÂÁö ¾Ë ¼ö ÀÖ½À´Ï´Ù. ½ÇÁ¦·Î ´ÙÀ½°ú °°Àº ŸÀÔÀ» ¸¸µé¾î¼­ ÀÌ ¹æ¹ýÀ» Àû¿ëÇÏ·Á°í ÇÕ´Ï´Ù (¾Æ·¡ Äڵ忡¼­ struct xmemheader´Â Figure 3.1ÀÇ ¡®size¡¯¿Í ¡®redzone¡¯À» À§ÇÑ °ÍÀ̸ç, struct xmemfooter´Â µÚ¿¡ ºÙ´Â redzoneÀ» À§ÇÑ °ÍÀÔ´Ï´Ù):
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;
¶Ç, ÇöÀç µ¿ÀûÀ¸·Î ¾òÀº ¸Þ¸ð¸®ÀÇ Å©±â¸¦ ÀúÀåÇϱâ À§ÇÑ ¡®xmem_cur_size¡¯¿Í, ÇÁ·Î¼¼½º°¡ µ¿Àû ¸Þ¸ð¸®¸¦ ¼ÒºñÇÑ ¾çÀÌ °¡Àå Ŭ ¶§ÀÇ °ªÀ» ÀúÀåÇϱâ À§ÇÑ ¡®xmem_max_size¡¯, °¡»óÀ¸·Î ¸Þ¸ð¸® Å©±â Á¦ÇÑÀ» µÎ±â À§ÇÑ ¡®xmem_limit¡¯À» ÁغñÇÕ´Ï´Ù:
static long xmem_limit = -1;
static size_t xmem_cur_size;
static size_t xmem_max_size;
¿¹»óÄ¡ ¸øÇß´ø ¿¡·¯°¡ ¹ß»ýÇßÀ» °æ¿ì, ¿¡·¯ ¸Þ½ÃÁö Ãâ·ÂÀ» À§ÇÑ ½ºÆ®¸²À» °¡¸®Å°´Â ¡®xmem_error_stream¡¯, ±×¸®°í ¿¡·¯°¡ ¹ß»ýÇßÀ» ¶§ ºÎ¸¦ ¿¡·¯ ó¸® ÇÔ¼ö¸¦ À§ÇÑ ¡®xalloc_failed_handler¡¯µµ ÁغñÇÕ´Ï´Ù. (ÀÌ µÎ º¯¼ö´Â ÀûÀýÇÑ ÃʱⰪÀ» ¹Ì¸® Á¤ÇØ ³õ¾Ò½À´Ï´Ù):
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;
}
xmalloc()¿¡ ÁÖ¾îÁø Å©±â°¡ 0ÀÎ °æ¿ì, ¿ì¸®´Â ÀÏ°ü¼ºÀÖ´Â µ¿ÀÛÀ» ¾ò±â À§ÇØ1, ±× Å©±â¸¦ 1·Î º¯°æÇÕ´Ï´Ù. ±× µÚ¿¡ malloc(3)À» ºÒ·¯ ¸Þ¸ð¸®¸¦ ¾ò°í – ptr_size()¿¡ ´ëÇؼ­´Â µÚ¿¡ ¼³¸íÇÕ´Ï´Ù – add_stat()À» È£ÃâÇÑ ´ÙÀ½, ¡®malloc_called¡¯¿¡ 1À» ´õÇÑ ´ÙÀ½, set_ptr()ÀÇ ¸®ÅÏ°ªÀ» µ¹·ÁÁÝ´Ï´Ù. ¸¶Âù°¡Áö·Î add_stat()°ú set_ptr()¿¡ ´ëÇؼ­´Â µÚ¿¡¼­ ¼³¸íÇÕ´Ï´Ù. ¸¸¾à malloc()ÀÌ ³ÎÀ» ¸®ÅÏÇ߰ųª, add_stat()ÀÌ -1À» ¸®ÅÏÇÑ °æ¿ì, xalloc_failed_handler°¡ ³ÎÀÌ ¾Æ´Ï¸é, ÀÌ ÇÔ¼ö Æ÷ÀÎÅÍ°¡ °¡¸®Å°´Â ÇÔ¼ö¸¦ ºÒ·¯¼­ ¿¡·¯¸¦ ó¸®ÇÕ´Ï´Ù. ¿¡·¯ ó¸® ÇÔ¼ö°¡ µî·ÏµÇ¾î ÀÖÁö ¾ÊÀº °æ¿ì³ª – xalloc_failed_handler°¡ ³ÎÀÎ °æ¿ì – ¿¡·¯ ó¸® ÇÔ¼ö°¡ ÇÁ·Î¼¼½º¸¦ Á¾·á½ÃÅ°Áö ¾Ê´õ¶óµµ xmalloc()Àº ¿Ã¹Ù¸£°Ô ³ÎÀ» ¸®ÅÏÇÏ´Â °ÍÀ» ¾Ë ¼ö ÀÖ½À´Ï´Ù. ¿¡·¯ ó¸® ÇÔ¼ö°¡ ¸®ÅÏµÈ ´ÙÀ½¿¡µµ, ³ÎÀ» ¸®ÅÏÇÏÁö ¾Ê°í, ¾û¸ÁÀ¸·Î Äڵ尡 Èê·¯°¡Áö ¾Êµµ·Ï Á¶½ÉÇØ¾ß ÇÕ´Ï´Ù. ptr_size(), set_ptr()Àº Figure 3.1¿¡¼­ ¼³¸íÇÑ °Íó·³ redzone 󸮸¦ ´ã´çÇÕ´Ï´Ù. ÀÏ´Ü ptr_size()´Â »ç¿ëÀÚ°¡ ¿äûÇÑ ¸Þ¸ð¸® »çÀÌÁî¿¡, Figure 3.1ÀÇ ¡®size¡¯¸¦ À§ÇÑ °ø°£ ´õÇϱ⠾յÚÀÇ redzoneÀ» À§ÇÑ Å©±â¸¦ ´õÇÑ °ªÀ» µ¹·ÁÁÝ´Ï´Ù:
static __inline__ size_t
ptr_size(size_t size)
{
  size += sizeof(struct xmemheader);
  size += sizeof(struct xmemfooter);
  return size;
}
setptr()Àº Figure 3.1¿¡ ³ª¿Â °Íó·³ redzone°ú size¸¦ ÃʱâÈ­Çϸç, ½ÇÁ¦ ÇÒ´çÇÑ ¸Þ¸ð¸® ºí·°ÀÇ ÁÖ¼Ò¸¦ ¹Þ¾Æ¼­, »ç¿ëÀÚ¿¡°Ô µ¹·ÁÁÙ ÁÖ¼Ò¸¦ °è»êÇÏ¿© µ¹·ÁÁÝ´Ï´Ù. (¾Æ·¡ Äڵ忡¼­ ¾´ XMEM_HEADER¿Í XMEM_FOOTER´Â ´Ü¼øÇÑ ¾î¶² ƯÁ¤ °ªÀÔ´Ï´Ù. ???ÀÇ ¼Ò½º¸¦ Âü°í ¹Ù¶ø´Ï´Ù):
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);
}
¸¶Áö¸·À¸·Î add_stat()Àº ÇöÀç±îÁö ÇÒ´çÇÑ ¸Þ¸ð¸® ºí·°µéÀÇ ÃÑ ÇÕ°ú, ÃÖ´ë·Î ÇÒ´çÇß´ø ¸Þ¸ð¸® ¾çÀ» °è»êÇϸç, ¸¸¾à ¡®xmem_limit¡¯°¡ ¾ç¼ö·Î ¼³Á¤µÇ¾î ÀÖÀ» °æ¿ì, ÇöÀç ÇÒ´çÇÑ ºí·°ÀÇ ÃÑ ÇÕÀÌ ÀÌ °ªÀ» ³ÑÁö ¾Ê´Â Áö °Ë»çÇÕ´Ï´Ù:
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 */



ID
Password
Join
You will be recognized and honored as a community leader.


sponsored by andamiro
sponsored by cdnetworks
sponsored by HP

Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2005-03-22 15:10:28
Processing time 0.0093 sec