clinuxaddress-sanitizerthread-sanitizer

How to get total heap memory allocated by the user when AddressSanitizer or ThreadSanitizer are enabled?


I want to get the amount of heap memory allocated with mallinfo2():

/*
 * File: main.c
*/

#include <malloc.h>
#include <stddef.h>
#include <stdio.h>

size_t GetHeapMemoryUsed() {
    struct mallinfo2 mi = mallinfo2();
    return mi.uordblks + mi.hblkhd;
}

int main(void) {
    size_t mem1 = GetHeapMemoryUsed();
    char *p = (char *)malloc(65536);
    size_t mem2 = GetHeapMemoryUsed();
    printf("Heap memory used: %zu\n", mem2 - mem1);
    free(p);
    return 0;
}

When I compile it with GCC (gcc -std=c99 main.c && ./a.out or g++ -std=c++11 main.cpp && ./a.out), it can give me the correct result:

Heap memory used: 65552

However, when I use AddressSanitizer or ThreadSanitizer (add an option -fsanitize=address or -fsanitize=thread), it gives me zero:

Heap memory used: 0

And mem1 and mem2 are all zero:

-    printf("Heap memory used: %zu\n", mem2 - mem1);
+    printf("Heap memory used: %zu\nmem1: %zu, mem2: %zu\n", mem2 - mem1, mem1, mem2);
Heap memory used: 0
mem1: 0, mem2: 0

It seems that AddressSanitizer and ThreadSanitizer take over the job of the malloc function and mallinfo2 cannot give the memory allocated.

Then how can I get the amount of heap memory allocated with AddressSanitizer or ThreadSanitizer enabled?


Solution

  • AFAICT, the sanitizer does not support mallinfo.

    Looking at the source for gcc to get the source for libasan.*, it specifically treats it as a dummy implementation ...


    From libsanitizer/asan/asan_malloc_linux.cc:

    #if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
    // We avoid including malloc.h for portability reasons.
    // man mallinfo says the fields are "long", but the implementation uses int.
    // It doesn't matter much -- we just need to make sure that the libc's mallinfo
    // is not called.
    struct fake_mallinfo {
      int x[10];
    };
    
    INTERCEPTOR(struct fake_mallinfo, mallinfo, void) {
      struct fake_mallinfo res;
      REAL(memset)(&res, 0, sizeof(res));
      return res;
    }
    
    INTERCEPTOR(int, mallopt, int cmd, int value) {
      return -1;
    }
    #endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
    

    From libsanitizer/sanitizer_common/sanitizer_platform_interceptors.h:

    #define SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO \
      (!SI_FREEBSD && !SI_MAC && !SI_NETBSD && SI_NOT_FUCHSIA)