Vasyl  Demianov
Vasyl Demianov

Reputation: 307

memory leaks detection: mallinfo, _heapwalk

My goal is to write platform-independent free memory checker. Something like:

std::size_t before = MemoryAllocated();
do_stuff(); //some algorithm that uses malloc, free, new, delete, etc
std::size_t after = MemoryAllocated();
if( after != before )
    printf( "ALARM! MEMORY LEAKS!\n" );

On POSIX there is mallinfo(), which provides pretty comprehensive free memory stats, one of the fields is uordblks, which seems to show exactly what I want. It includes the overhead - for instance it shows that new int on my machine allocates 32 bytes. But in the end of the day if you deallocaed everything - it shows 0, if you forgot something - it is non-zero.

On Windows there is _heapwalk(). It is a bit more complicated than mallinfo() - you need to iterate through heap chunks and compute the size yourself. And even after you did it, the result isn't quite what I expect:

int main()
{
    std::cout << "start " << MemoryAllocated() << std::endl;

    char *charr = new char[100];
    std::cout << "after new char[100] " << MemoryAllocated() << std::endl;

    int *pint = new int;
    std::cout << "after new int " << MemoryAllocated() << std::endl;

    delete[] charr;
    std::cout << "after delete[] chars " << MemoryAllocated() << std::endl;

    delete pint;
    std::cout << "after delete int " << MemoryAllocated() << std::endl;

    return 0;
}

results in:

start 26980
after new char[100] 31176
after new int 31180
after delete[] chars 31080
after delete int 31076

Looks like it allocates some initial 4 kbytes of memory for his internal needs on my first request to allocated memory, but then it shows current status accurately.

I tried to preallocate something before starting the real count - it doesn't help.

Can anybody hint me, how to do it properly on Windows?

Upvotes: 2

Views: 588

Answers (1)

arye
arye

Reputation: 500

I wrote a C code that seems to work but in a weird way, seems, like your results, that there is ~4K memory that allocated in the beginning, but it allocated between first check to the second. So if we ignore it we get correct answer:

#include <stdio.h>
#include <stdlib.h>

int MemoryAllocated()
{
    _HEAPINFO hinfo;
    int heapstatus;
    hinfo._pentry = NULL;
    int ans = 0;
    while((heapstatus = _heapwalk(&hinfo)) == _HEAPOK)
    {
        if(hinfo._useflag == _USEDENTRY)
        {
            ans += hinfo._size;
        }
    }

    switch(heapstatus)
    {
    case _HEAPEMPTY:
        printf("ERROR - empty heap\n");
        exit(-1);
        break;
    case _HEAPBADPTR:
        printf("ERROR - bad pointer to heap\n");
        exit(-1);
        break;
    case _HEAPBADBEGIN:
        printf("ERROR - bad start of heap\n");
        exit(-1);
        break;
    case _HEAPBADNODE:
        printf("ERROR - bad node in heap\n");
        exit(-1);
        break;
    }

    return ans;
}

int main(void) {
    int dummy_start_alloc, start_alloc, end_alloc;

    dummy_start_alloc = MemoryAllocated();
    printf("dummy start %d\n", dummy_start_alloc);

    start_alloc = MemoryAllocated();
    printf("real start %d\n", start_alloc);

    if(dummy_start_alloc != start_alloc)
    {
        printf("It is weird why dummy start is different than second start\n");
    }

    char *charr = malloc(sizeof(char[100]));
    printf("after malloc char[100] %d\n", MemoryAllocated());

    int *pint = malloc(sizeof(int));
    printf("after malloc int %d\n", MemoryAllocated());

    free(charr);
    printf("after free chars %d\n", MemoryAllocated());

    free(pint);
    end_alloc = MemoryAllocated();
    printf("after free int %d\n", end_alloc);

    if(start_alloc == end_alloc)
    {
        printf("no memory leak detected");
    }
    else
    {
        printf("ERROR - memory leak detected");
    }

    return EXIT_SUCCESS;
}

Output for me is:

dummy start 14878
real start 18974
It is weird why dummy start is different than second start
after malloc char[100] 19074
after malloc int 19078
after free chars 18978
after free int 18974
no memory leak detected

Upvotes: 0

Related Questions