`getaddrinfo()`的内存分配

时间:2016-12-25 04:35:07

标签: memory memory-leaks

我有一个简单的程序,可以调用getaddrinfo()freeaddrinfo()。 我在上面运行valgrind,它表明没有内存泄漏。

in use at exit: 0 bytes in 0 blocks
total heap usage: 108 allocs, 109 frees

但是,我编写了一个名为memleax的内存调试器,它将目标进程和陷阱附加到malloc()free()以检测内存泄漏。我使用memleax来检测getaddrinfo()程序,它只捕获free() 43次。

然后我将malloc()free()挂钩到malloc-hooks, 它还显示free()只有43次。

所以我的问题是,valgrind和hooking-malloc之间有什么区别?

原始代码:

#include <sys/types.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>

int main()
{
  struct addrinfo *aihead;

  sleep(4);
  printf(" --- getaddrinfo ---\n");
  int error = getaddrinfo("dig.chouti.com", "http", NULL, &aihead);
  if(error) {
    printf("error: %s\n", gai_strerror(error));
    return error;
  }
  sleep(4);
  printf("\n\n\n --- freeaddrinfo ---\n");
  freeaddrinfo(aihead);
  sleep(4);
  return 0;
}

使用malloc-hook的代码

#include <sys/types.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>

/* Prototypes for __malloc_hook, __free_hook */
#include <malloc.h>

/* Prototypes for our hooks.  */
static void my_init_hook (void);
static void *my_malloc_hook (size_t, const void *);
static void my_free_hook (void*, const void *);

static void *(*old_malloc_hook) (size_t, const void *);
static void (*old_free_hook) (void*, const void *);

static void
my_init (void)
{
  old_malloc_hook = __malloc_hook;
  old_free_hook = __free_hook;
  __malloc_hook = my_malloc_hook;
  __free_hook = my_free_hook;
}

static void *
my_malloc_hook (size_t size, const void *caller)
{
  void *result;
  /* Restore all old hooks */
  __malloc_hook = old_malloc_hook;
  __free_hook = old_free_hook;
  /* Call recursively */
  result = malloc (size);
  /* Save underlying hooks */
  old_malloc_hook = __malloc_hook;
  old_free_hook = __free_hook;
  /* printf might call malloc, so protect it too. */
  printf ("malloc (%u) returns %p\n", (unsigned int) size, result);
  /* Restore our own hooks */
  __malloc_hook = my_malloc_hook;
  __free_hook = my_free_hook;
  return result;
}

static void
my_free_hook (void *ptr, const void *caller)
{
  /* Restore all old hooks */
  __malloc_hook = old_malloc_hook;
  __free_hook = old_free_hook;
  /* Call recursively */
  free (ptr);
  /* Save underlying hooks */
  old_malloc_hook = __malloc_hook;
  old_free_hook = __free_hook;
  /* printf might call free, so protect it too. */
  printf ("freed pointer %p\n", ptr);
  /* Restore our own hooks */
  __malloc_hook = my_malloc_hook;
  __free_hook = my_free_hook;
}

int main()
{
  my_init();

  struct addrinfo *aihead;

  printf(" --- getaddrinfo ---\n");
  int error = getaddrinfo("dig.chouti.com", "http", NULL, &aihead);
  if(error) {
    printf("error: %s\n", gai_strerror(error));
    return error;
  }
  sleep(4);
  printf("\n\n\n --- freeaddrinfo ---\n");
  freeaddrinfo(aihead);
  sleep(4);
  return 0;
}

1 个答案:

答案 0 :(得分:1)

我在valgrind的输出中找到了这个:

--13197-- Discarding syms at 0x55f9240-0x5600454 in /usr/lib64/libnss_files-2.17.so due to mu
--13197-- Discarding syms at 0x580b100-0x580e590 in /usr/lib64/libnss_dns-2.17.so due to munm
--13197-- Discarding syms at 0x5a13a40-0x5a22854 in /usr/lib64/libresolv-2.17.so due to munma
==13197== Invalid free() / delete / delete[] / realloc()
==13197==    at 0x4C2AD17: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==13197==    by 0x4F9963B: __libc_freeres (in /usr/lib64/libc-2.17.so)
==13197==    by 0x4A246B4: _vgnU_freeres (in /usr/lib64/valgrind/vgpreload_core-amd64-linux.s
==13197==    by 0x4E6DE2A: __run_exit_handlers (in /usr/lib64/libc-2.17.so)
==13197==    by 0x4E6DEB4: exit (in /usr/lib64/libc-2.17.so)
==13197==    by 0x4E56B1B: (below main) (in /usr/lib64/libc-2.17.so)
==13197==  Address 0x51f03d0 is 0 bytes inside data symbol "noai6ai_cached"

似乎libc-nss在exit()之后释放了__run_exit_handlers()处的一些内存。

因此,valgrid可能会在目标进程的exit()之后继续跟踪内存。而malloc-hook在exit()之后停止工作。