资源泄漏的调试

资源泄漏就是进程向系统申请了资源但是用完了没有还给系统,造成了系统资源一直被占用,无法重复利用。系统资源有限,资源泄漏的后果就是资源耗尽。

简单的句柄泄漏

以如下代码生成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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值