views:

54

answers:

2

On my Windows 7 box, this simple program causes the memory use of the application to creep up continuously, with no upper bound. I've stripped out everything non-essential, and it seems clear that the culprit is the Microsoft Iphlpapi function "GetIpAddrTable()". On each call, it leaks some memory. In a loop (e.g. checking for changes to the network interface list), it is unsustainable. There seems to be no async notification API which could do this job, so now I'm faced with possibly having to isolate this logic into a separate process and recycle the process periodically -- an ugly solution.

Any ideas?

// IphlpLeak.cpp - demonstrates that GetIpAddrTable leaks memory internally:  run this and watch
// the memory use of the app climb up continuously with no upper bound.
#include <stdio.h>
#include <windows.h>
#include <assert.h>
#include <Iphlpapi.h>
#pragma comment(lib,"Iphlpapi.lib")

void testLeak() {
    static unsigned char buf[16384];
    DWORD dwSize(sizeof(buf));
    if (GetIpAddrTable((PMIB_IPADDRTABLE)buf, &dwSize, false) == ERROR_INSUFFICIENT_BUFFER)
    {
        assert(0); // we never hit this branch.
        return;
    }
}
int main(int argc, char* argv[]) {
    for ( int i = 0; true; i++ )    {
        testLeak();
        printf("i=%d\n",i); 
        Sleep(1000);
    }
    return 0;
}
+1  A: 

Just for the sake of completeness, what happens to memory usage if you comment out the entire if block and the sleep? If there's no leak there, then I would suggest you're correct as to what's causing it.

Worst case, report it to MS and see if they can fix it - you have a nice simple test case to work from which is more than what I see in most bug reports.

Another thing you may want to try is to check the error code against NO_ERROR rather than a specific error condition. If you get back a different error than ERROR_INSUFFICIENT_BUFFER, there may be a leak for that:

DWORD dwRetVal = GetIpAddrTable((PMIB_IPADDRTABLE)buf, &dwSize, false);
if (dwRetVal != NO_ERROR) {
    printf ("ERROR: %d\n", dwRetVal);
}
paxdiablo
Thanks -- yes, the code stops leaking if I stop calling GetIpAddrTable. The idea of checking for an alternate return code is good, but the production code does that -- the leak persists. As for notifying Microsoft... well, I suppose I have some community obligation to do so, but in terms of solving my problem so I can ship the product, that's not really practical.I'm thinking about switching gears entirely -- call gethostname(), and then gethostbyname() to retrieve the list of IPs bound to that name. It should suffice, although it leaves this irritating mystery.
Stabledog
A: 

I've been all over this issue now: it appears that there is no acknowledgment from Microsoft on the matter, but even a trivial application grows without bounds on Windows 7 (not XP, though) when calling any of the APIs which retrieve the local IP addresses.

So the way I solved it -- for now -- was to launch a separate instance of my app with a special command-line switch that tells it "retrieve the IP addresses and print them to stdout". I scrape stdout in the parent app, the child exits and the leak problem is resolved.

But it wins "dang ugly solution to an annoying problem", at best.

Stabledog