· 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
Mind your own business, Spock. I'm sick of your halfbreed interference.


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.0098 sec