资源泄漏就是进程向系统申请了资源但是用完了没有还给系统,造成了系统资源一直被占用,无法重复利用。系统资源有限,资源泄漏的后果就是资源耗尽。
简单的句柄泄漏
以如下代码生成exe:
#ifndef __SRV_H
#define __SRV_H
#include <windows.h>
class CServer
{
public:
static BOOL GetTextFileContents(HANDLE hEvent, PWSTR pszFileName, PSTR pBuffer, DWORD dwBufferLen);
private:
CServer(){};
~CServer(){};
static DWORD WINAPI RequestWorker(LPVOID lpParameter);
struct WorkerData
{
PWSTR pszFileName;
PSTR pBuffer;
DWORD dwBufferLen;
HANDLE hCompletionHandle;
} ;
} ;
#endif
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "srv.h"
BOOL CServer::GetTextFileContents(HANDLE hEvent,
PWSTR pszFileName,
PSTR pBuffer,
DWORD dwBufferLen)
{
BOOL bRet=FALSE;
if(hEvent!=NULL && pszFileName!=NULL && pBuffer!=NULL && dwBufferLen!=0)
{
WorkerData* pWorkerData=new WorkerData;
if(pWorkerData!= NULL)
{
pWorkerData->dwBufferLen=dwBufferLen;
pWorkerData->pBuffer=pBuffer;
pWorkerData->pszFileName=pszFileName;
pWorkerData->hCompletionHandle=hEvent;
bRet=QueueUserWorkItem(RequestWorker,
(LPVOID) pWorkerData,
WT_EXECUTELONGFUNCTION);
if(!bRet)
{
delete pWorkerData;
}
}
}
return bRet;
}
DWORD WINAPI CServer::RequestWorker(LPVOID lpParameter)
{
DWORD dwRet=0;
WorkerData* pWorkerData=reinterpret_cast<WorkerData*>(lpParameter);
HANDLE hFile=CreateFile(pWorkerData->pszFileName,
FILE_READ_DATA,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(hFile!=INVALID_HANDLE_VALUE)
{
DWORD dwBytesRead=0;
BOOL bRet=ReadFile(hFile,
(LPVOID) pWorkerData->pBuffer,
(pWorkerData->dwBufferLen-1),
&dwBytesRead,
NULL);
if(bRet==TRUE)
{
dwRet=1;
}
}
SetEvent(pWorkerData->hCompletionHandle);
delete pWorkerData;
return dwRet;
}
#include <windows.h>
#include <strsafe.h>
#include <stdio.h>
#include "srv.h"
#define MAX_LEN 255
void __cdecl wmain()
{
wprintf(L"Client application console menu\n");
wprintf(L"================================\n");
HANDLE hCompletionEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
if(hCompletionEvent==NULL)
{
wprintf(L"\nFailed to create a new event\n");
return;
}
BOOL bContinue=TRUE;
while(bContinue)
{
wprintf(L"Enter filename to read > ");
WCHAR pFileName[MAX_LEN];
StringCchGets(pFileName, MAX_LEN);
if(wcslen(pFileName))
{
CHAR szFiledata[1024];
memset(szFiledata, 0, 1024);
BOOL bRet=CServer::GetTextFileContents(hCompletionEvent,
pFileName,
szFiledata, 1024 ) ;
if(bRet==FALSE)
{
wprintf(L"\nFailed to read file\n");
}
else
{
wprintf(L"\nScheduled request successfully\n");
if(WaitForSingleObject(hCompletionEvent, INFINITE)!=WAIT_FAILED)
{
printf("\nData read:\n%s\n", szFiledata);
}
}
}
else
{
wprintf(L"Exiting application...\n");
bContinue=FALSE;
}
}
CloseHandle(hCompletionEvent);
}
运行程序,读取文件多次后发现句柄数一直增长并空闲一段时候后并没有减少的情况,初步判断存在句柄泄漏:
通过process explorer能查看到更多的信息:
a.txt打开之后一直没有关闭,a.txt是用户的输入,跟踪参数的传递路径可以轻易找到函数RequestWorker存在泄漏。
更复杂的泄漏
我们使用模拟句柄随机泄漏的情况:
#ifndef __SRV_H
#define __SRV_H
#include <windows.h>
class CServer
{
public:
CServer(){};
~CServer(){};
PSID GetSID();
DWORD GetPrivilegeCount();
DWORD GetGroupCount();
private:
HANDLE GetToken();
} ;
#endif
#include "srv.h"
#include <windows.h&g