[英]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);
然后开始调试……当然! 您不能释放原始的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.