1
votes

I am trying to debug a memory leak in a 64-bit C++ native application. The app leaks 1300 bytes 7-10 times a second - via plain malloc().

If I attach to the process with WinDBG and break into it every 60 seconds, !heap does not show any increase in memory allocated.

I did enable User Mode Stack trace database on the process:

gflags /i <process>.exe +ust

In WinDBG (with all the symbols successfully loaded), I'm using:

!heap -stat -h

But the output of the command never changes when I break in even though I can see the Private Bytes increase in Task Manager and a PerfMon trace.

I understand that when allocations are small they go to HeapAlloc(), when they're bigger they go to VirtualAlloc. Does !heap not work for HeapAlloc?

This post seems to imply that maybe using DebugDiag would work, but it still boils down to using WinDBG commands to process the dump. Tried to no avail.

This post also says that !heap command is broken for 64-bit apps. Could that be the case?

Is there an alternate procedure for diagnosing leaks in 64-bit apps?

1
There were no dumps involved when using WinDBG. I was attaching to the process directly. In any case UMDH did not show any leaks either.pathrider
You'd better open a support case via support.microsoft.com to get some help. It is too broad to discuss such on SO, as nobody can reproduce what you have.Lex Li
Do you have a minimal reproducible example? Your first paragraph sounds like this can be implemented in 20 lines of code. Can you give us something we could try? Can you share the app or dmp files?Thomas Weller
It's 4.5M lines of code. I'll see if I can create a managable example.pathrider

1 Answers

1
votes

 !heap does not show any increase in memory allocated.

That may depend on which column you're looking at and how much memory the heap manager has allocated before.

E.g. it's possible that your application has a heap of 100 MB, of which just some blocks of 64kB are moving from the "reserved" column to the "committed" column. If the memory is committed right from the start, you won't see anything at all with a plain !heap command.

I did enable User Mode Stack trace database on the process

That will help you getting the allocation stack traces, but not affect the leak in general.

I understand that when allocations are small they go to HeapAlloc(), when they're bigger they go to VirtualAlloc.

Yes, for allocations > 512k.

Does !heap not work for HeapAlloc?

It should. And since C++ malloc() and new both use the Windows Heap manager, they should result in HeapAlloc() sooner or later.

The following code

#include <iostream>
#include <chrono>
#include <thread>

int main()
{
    // https://stackguides.com/questions/53157722/windbg-diagnosing-leaks-in-64-bit-dumps-heap-not-showing-memory-growth
    //
    // I am trying to debug a memory leak in a 64-bit C++ native application.
    // The app leaks 1300 bytes 7-10 times a second - via plain malloc().

    for(int seconds=0; seconds < 60; seconds++)
    {
        for (int leakspersecond=0; leakspersecond<8;leakspersecond++)
        {
            if (malloc(1300)==nullptr)
            {
                std::cout << "Out of memory. That was unexpected in this simple demo." << std::endl;
            }
            std::this_thread::sleep_for(std::chrono::milliseconds(125));
        }
    }
}

compiled as 64 bit release build and run in WinDbg 10.0.15063.400 x64 shows

0:001> !heap -stat -h

Allocations statistics for
 heap @ 00000000000d0000
group-by: TOTSIZE max-display: 20
    size     #blocks     total     ( %) (percent of total busy bytes)
    514 1a - 8408  (32.24)
    521 c - 3d8c  (15.03)
[...]

and later

0:001> !heap -stat -h

Allocations statistics for
 heap @ 00000000000d0000
group-by: TOTSIZE max-display: 20
    size     #blocks     total     ( %) (percent of total busy bytes)
    514 30 - f3c0  (41.83)
    521 18 - 7b18  (21.12)

even without +ust set.

It's 4.5M lines of code.

How do you then know that it leaks 1300 bytes via plain malloc()?