繁体   English   中英

使用DnsGetCacheDataTable时发生内存泄漏

[英]Memory leak when using DnsGetCacheDataTable

以下代码显示DNS客户端中的缓存域名。 当有人遇到int stat = DnsGetCacheDataTable(pEntry);时,有人可以帮我找到内存泄漏吗? 线?
PS:请在编译代码时使用DNSAPI.lib。

#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <WinDNS.h>
#include <stdarg.h>
typedef struct _DNS_CACHE_ENTRY {
    struct _DNS_CACHE_ENTRY* pNext; // Pointer to next entry
    PWSTR pszName; // DNS Record Name
    unsigned short wType; // DNS Record Type
    unsigned short wDataLength; // Not referenced
    unsigned long dwFlags; // DNS Record FlagsB
} DNSCACHEENTRY, *PDNSCACHEENTRY;

typedef int(WINAPI *DNS_GET_CACHE_DATA_TABLE)(PDNSCACHEENTRY);
void UpdateDNS(void)
{

    PDNSCACHEENTRY pEntry = (PDNSCACHEENTRY) malloc(sizeof(DNSCACHEENTRY));
    // Loading DLL
    HINSTANCE hLib = LoadLibrary(TEXT("DNSAPI.dll"));
    // Get function address
    DNS_GET_CACHE_DATA_TABLE DnsGetCacheDataTable = (DNS_GET_CACHE_DATA_TABLE) GetProcAddress(hLib, "DnsGetCacheDataTable");
    int stat = DnsGetCacheDataTable(pEntry);
    printf("stat = %d\n", stat);
    pEntry = pEntry->pNext;
    while (pEntry) {
        wprintf(L"%s : %d \n", (pEntry->pszName), (pEntry->wType));
        pEntry = pEntry->pNext;
    }
    free(pEntry);
}

int main(int argc, char **argv) {

    while (TRUE)
    {
        Sleep(100);
        UpdateDNS();
    }   
    return 0;
}

此代码存在几个问题。

考虑到您是在开始时调用LoadLibrary而不在结束时调用FreeLibrary 虽然从技术上讲不是内存泄漏,但这可能不是最聪明的主意。

考虑到通过在循环之前直接移到pEntry->pNext ,可以跳过一个条目。 当您分配malloc返回的值时,在同一行代码中就会发生内存泄漏:

PDNSCACHEENTRY pEntry = (PDNSCACHEENTRY) malloc(sizeof(DNSCACHEENTRY));
/* ... */
pEntry = pEntry->pNext;

您甚至不需要malloc ,但更糟糕的是,您应该只free malloc返回的值,从而导致以下错误:

free(pEntry);

实际上,您不仅不需要malloc (或free ),而且实际上需要的是DnsRecordListFree

您的代码可能看起来像这样:

PDNS_RECORD entry;
HINSTANCE hLib = LoadLibrary(TEXT("DNSAPI.dll"));
DNS_GET_CACHE_DATA_TABLE DnsGetCacheDataTable = (DNS_GET_CACHE_DATA_TABLE) GetProcAddress(hLib, "DnsGetCacheDataTable");
int stat = DnsGetCacheDataTable(&entry);
printf("stat = %d\n", stat);
for (DNSCACHEENTRY *pTemp = &entry; pTemp; pTemp = pTemp->pNext) {
    wprintf(L"%s : %d \n", pTemp->pszName, pTemp->wType);
}
DnsRecordListFree(entry, DnsFreeRecordList);

与Deleaker一起尝试过,因为乍一看代码看起来不错: 泄漏

然后开始调试……当然! 您不能释放原始的pEntry,而可以修改一个。

这里是更正的代码:

void UpdateDNS(void)
{

    PDNSCACHEENTRY pEntry = (PDNSCACHEENTRY) malloc(sizeof(DNSCACHEENTRY) + 0x10000);
    PDNSCACHEENTRY pFirstEntry = pEntry;
    // Loading DLL
    HINSTANCE hLib = LoadLibrary(TEXT("DNSAPI.dll"));
    // Get function address
    DNS_GET_CACHE_DATA_TABLE DnsGetCacheDataTable = (DNS_GET_CACHE_DATA_TABLE) GetProcAddress(hLib, "DnsGetCacheDataTable");
    int stat = DnsGetCacheDataTable(pEntry);
    printf("stat = %d\n", stat);
    pEntry = pEntry->pNext;
    while (pEntry) {
        wprintf(L"%s : %d \n", (pEntry->pszName), (pEntry->wType));
        pEntry = pEntry->pNext;
    }
    free(pFirstEntry);
}

更新:实际上,您不需要分配任何内存,因为DnsGetCacheDataTable本身已分配了它。 试图使用DnsRecordListFree释放内存,但似乎不起作用。 仍然泄漏:

仍然泄漏

最终,我得到了不会泄漏的代码:

typedef int(WINAPI *DNS_GET_CACHE_DATA_TABLE)(PDNSCACHEENTRY*);

typedef void (WINAPI *P_DnsApiFree)(PVOID pData);

void UpdateDNS(void)
{
    PDNSCACHEENTRY pEntry = NULL;
    // Loading DLL
    HINSTANCE hLib = LoadLibrary(TEXT("DNSAPI.dll"));
    // Get function address
    DNS_GET_CACHE_DATA_TABLE DnsGetCacheDataTable = (DNS_GET_CACHE_DATA_TABLE)GetProcAddress(hLib, "DnsGetCacheDataTable");
    P_DnsApiFree pDnsApiFree = (P_DnsApiFree)GetProcAddress(hLib, "DnsApiFree");
    int stat = DnsGetCacheDataTable(&pEntry);
    PVOID pFirstEntry = pEntry;
    printf("stat = %d\n", stat);
    pEntry = pEntry->pNext;
    while (pEntry) {
        wprintf(L"%s : %d \n", (pEntry->pszName), (pEntry->wType));
        pDnsApiFree(pEntry->pszName);
        PVOID p = pEntry;
        pEntry = pEntry->pNext;
        pDnsApiFree(p);
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM