If you'd like to observe heap memory getting allocated and freed (for unordered_map
or for anything else) you can always overload the global new
and delete
operators to keep track of the tally and/or print out the current tally as you go. (Note: example code shown below isn't thread safe, and probably won't work reliably outside of simple toy programs, but it's good enough to experiment with)
# include <stdint.h>
# include <new>
# include <typeinfo>
# include <unordered_map>
static inline uint32_t CONVERT_USER_TO_INTERNAL_SIZE(uint32_t uNumBytes) {return (uNumBytes+sizeof(size_t));}
static inline uint32_t CONVERT_INTERNAL_TO_USER_SIZE(uint32_t iNumBytes) {return (iNumBytes-sizeof(size_t));}
static inline size_t * CONVERT_USER_TO_INTERNAL_POINTER(void * uptr) {return (((size_t*)uptr)-1);}
static inline void * CONVERT_INTERNAL_TO_USER_POINTER(size_t * iptr) {return ((void *)(iptr+1));}
static size_t _currentlyAllocatedBytes = 0; // Running tally of how many bytes our process has allocated
void * instrumentedAlloc(size_t userSize)
{
const size_t internalSize = CONVERT_USER_TO_INTERNAL_SIZE(userSize);
void * userPtr = NULL;
size_t * internalPtr = (size_t *) malloc(internalSize);
if (internalPtr)
{
*internalPtr = internalSize; // our little header tag so that instrumentedFree() will know how big the allocation was
_currentlyAllocatedBytes += internalSize;
printf("instrumentedAlloc(%zu): total allocation count is now %zu\n", internalSize, _currentlyAllocatedBytes);
userPtr = CONVERT_INTERNAL_TO_USER_POINTER(internalPtr);
}
return userPtr;
}
void instrumentedFree(void * userPtr)
{
if (userPtr)
{
size_t * internalPtr = CONVERT_USER_TO_INTERNAL_POINTER(userPtr);
const size_t allocationSize = *internalPtr;
_currentlyAllocatedBytes -= allocationSize;
printf("instrumentedFree(%p,%zu): total allocation count is now %zu\n", userPtr, allocationSize, _currentlyAllocatedBytes);
free(internalPtr);
}
}
void * operator new(size_t s) throw ( std::bad_alloc )
{
void * ret = instrumentedAlloc(s);
if (ret == NULL) {throw std::bad_alloc ( );}
return ret;
}
void * operator new[](size_t s) throw ( std::bad_alloc )
{
void * ret = instrumentedAlloc(s);
if (ret == NULL) {throw std::bad_alloc ( );}
return ret;
}
void operator delete( void * p) throw() {instrumentedFree(p);}
void operator delete[](void * p) throw() {instrumentedFree(p);}
int main(int, char **)
{
printf("ABOUT TO DECLARE test_map\n");
std::unordered_map<int, int> test_map;
printf("ABOUT TO POPULATE test_map\n");
for (int i=0; i<10; i++) test_map[i] = i;
printf("ABOUT TO CLEAR test_map\n");
test_map.clear();
return 0;
}
... when run, the above program prints this output on my machine:
Jeremys-Mac-mini-2:~ jaf$ ./a.out
ABOUT TO DECLARE test_map
ABOUT TO POPULATE test_map
instrumentedAlloc(32): total allocation count is now 32
instrumentedAlloc(24): total allocation count is now 56
instrumentedAlloc(32): total allocation count is now 88
instrumentedAlloc(32): total allocation count is now 120
instrumentedAlloc(48): total allocation count is now 168
instrumentedFree(0x600003be1128,24): total allocation count is now 144
instrumentedAlloc(32): total allocation count is now 176
instrumentedAlloc(32): total allocation count is now 208
instrumentedAlloc(32): total allocation count is now 240
instrumentedAlloc(96): total allocation count is now 336
instrumentedFree(0x6000035e0248,48): total allocation count is now 288
instrumentedAlloc(32): total allocation count is now 320
instrumentedAlloc(32): total allocation count is now 352
instrumentedAlloc(32): total allocation count is now 384
instrumentedAlloc(32): total allocation count is now 416
ABOUT TO CLEAR test_map
instrumentedFree(0x600003be1228,32): total allocation count is now 384
instrumentedFree(0x600003be1208,32): total allocation count is now 352
instrumentedFree(0x600003be11e8,32): total allocation count is now 320
instrumentedFree(0x600003be11c8,32): total allocation count is now 288
instrumentedFree(0x600003be11a8,32): total allocation count is now 256
instrumentedFree(0x600003be1188,32): total allocation count is now 224
instrumentedFree(0x600003be1128,32): total allocation count is now 192
instrumentedFree(0x600003be1168,32): total allocation count is now 160
instrumentedFree(0x600003be1148,32): total allocation count is now 128
instrumentedFree(0x600003be1108,32): total allocation count is now 96
instrumentedFree(0x600001fe00c8,96): total allocation count is now 0