wub
wub

Reputation: 485

memory allocation of `getaddrinfo()`

I have a simple program which calls getaddrinfo() and freeaddrinfo(). I run valgrind on it, and it shows that there is no memory leak.

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

However, I wrote a memory debugger named memleax which attaches the target process and traps at malloc() and free() to detect memory leak. I use memleax to detect the getaddrinfo() program, and it catches free() only 43 times.

Then I hook the malloc() and free() by malloc-hooks, and it also shows free() only 43 times.

So my question is that, what is the difference between valgrind and hooking-malloc?

Original code:

#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;
}

Code with 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;
}

Upvotes: 2

Views: 1473

Answers (1)

wub
wub

Reputation: 485

I find this in valgrind's output:

--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"

It seems that libc-nss frees some memory at __run_exit_handlers() after exit().

So maybe valgrid keeps tracing memory after target process's exit(). While malloc-hook stops working after exit().

Upvotes: 1

Related Questions