Any way to find size of memory allocated to map?

Viewed 16280

Is there any method to find the amount/size of memory allocated to a map in c++? There is a function to find the size of the map,ie,number of entries in the map, but is there any such method for the memory. I have a map ( string, string). The sizeof() is always giving me a size of 48. Any reason why this is so? Thanks :)

6 Answers

Since google lead me here, I'll post a little late answer anyway -- since the accepted answer does not answer the question.

Here is what I did (along the lines suggested by Damon), which depends on the malloc implementation. On glibc/linux, the position just behind the returned pointer gives the size of the allocation, therefore, one can use the following code to track bytes allocated/deallocated:

#define HEAP_TRACE

#include <new>

static size_t                             heap_trace_allocated_bytes            = 0;
static size_t                             heap_trace_deallocated_bytes          = 0;
static size_t                             heap_trace_allocated_bytes_baseline   = 0;
static size_t                             heap_trace_deallocated_bytes_baseline = 0;

void* operator new(std::size_t size) {
    void* alloc_entry = std::malloc(size);
    if (!alloc_entry) {
        throw std::bad_alloc();
    }
    heap_trace_allocated_bytes += *(size_t*)(((size_t)alloc_entry)-sizeof(size_t));
    //std::cout << "(-1) equals " << size << " : " << *(size_t*)(((size_t)alloc_entry)-sizeof(size_t)) << std::endl << std::flush;
    return alloc_entry;
}

void operator delete(void* alloc_entry) noexcept {
    heap_trace_deallocated_bytes += *(size_t*)(((size_t)alloc_entry)-sizeof(size_t));
    //std::cout << "(-1) : " << *(size_t*)(((size_t)alloc_entry)-sizeof(size_t)) << std::endl << std::flush;
    std::free(alloc_entry);
}

void setHeapTraceBaseline() {
    heap_trace_allocated_bytes_baseline   = heap_trace_allocated_bytes;
    heap_trace_deallocated_bytes_baseline = heap_trace_deallocated_bytes;
}

void getHeapTraceInfo(string title) {
    std::cout << "\t" << title << ":" << std::endl;
    std::cout << "\t\tAllocations:   " << (heap_trace_allocated_bytes   - heap_trace_allocated_bytes_baseline)   << " bytes" << std::endl;
    std::cout << "\t\tDeallocations: " << (heap_trace_deallocated_bytes - heap_trace_deallocated_bytes_baseline) << " bytes" << std::endl;
    std::cout << std::endl << std::flush;
}

and the usage goes as follows:

setHeapTraceBaseline();
// your algorithms
getHeapTraceInfo("My Algorithm allocation costs");

Hope this helps someone.

Note: That was not meant for use in production, since my new is not reentrant. I ran it successfully while multithread unit testing, though.

This is a good question because other answers assume a fixed size of map elements. In my case I have a map of maps of maps of structs, which size() does not help to evaluate.

I solved this problem by hooking into the malloc function, and then creating a direct copy of the object of interest using a template function, which will automatically perform allocations of each sub-object, giving the gross size of the container and its contents.

#include <malloc.h>

size_t bucket = 0;

static void* plumber_hook(size_t size, const void* caller);
static void* plumber_hook(size_t size, const void* caller)
{
    void*   result;

    /* Restore all old hooks */
    /* Call recursively */
    __malloc_hook       = 0;
    {
        result = malloc(size);
    }
    __malloc_hook       = plumber_hook;

    bucket += size;

    return result;
}


template<typename T>
size_t plumberTest(T& t)
{
    //begin plumbing
    bucket = 0;
    
    __malloc_hook   = plumber_hook;
    {
        T newT = t;
    }
    __malloc_hook   = 0;

    return bucket;
}

void plumber()
{
    size_t gross_size = plumberTest(someMap);   
    printf("someMap and its contents uses at least %ld bytes of space\n", gross_size);
}
Related