Страница 1 из 1

IOCP и возможная утечка памяти

Добавлено: 05 окт 2012, 13:59
_angry
Делаю приложение на IOCP. Заметил, что после подключения и отключения клиентов количество дескрипторов (в диспетчере задач) не возвращается к первоначальному. Упростил всю логику до предела. Ниже полный код класса, при работе которого видна утечка хэндлов. Это демка, упрощенная до нельзя. Буду очень благодарен, если вы попробуете собрать проект у себя и выскажете свои мысли. Делаем пустой консольный проект с поддержкой mfc, в _tmain создаем экземпляр класса, вызываем метод Start. Нужна помощь. У кого какие мысли?
header

Код: Выделить всё

#include "Mutex.h"

typedef struct
{
	void * m_This;
	int    m_ThreadNumber;
}TIOCPParams;

typedef struct 
{
	OVERLAPPED m_ovrl;
	SOCKET     m_sock;  
}TMYOVERLAPPED;

class CD2Class  
{
public:
	int IOCPThread(TIOCPParams * pParams);
	int Stop();
	int Start();

	CD2Class();
	virtual ~CD2Class();

	HANDLE m_threadEvent;
	HANDLE m_hIocp;
	CMutex m_Mutex;
	int m_stop;
	int m_opcnt;
};
source

Код: Выделить всё

int gIOCPThread(void * pParams)
{
	TIOCPParams ThreadParams = *(TIOCPParams *)pParams;
	CD2Class * pD2 = (CD2Class *)ThreadParams.m_This;
	return pD2->IOCPThread( &ThreadParams );
}

CD2Class::CD2Class() : m_Mutex(0)
{
	m_stop = 0;
	m_hIocp = NULL;
	m_threadEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
	m_opcnt = 0;
}

CD2Class::~CD2Class()
{
	CloseHandle( m_threadEvent );
}

int CD2Class::Start()
{
	int i, nRet = 0, threads = 1, cnt = 0;	
	struct sockaddr_in addr;			
	WSAData	wsData;		
	SYSTEM_INFO si;
	struct sockaddr_in clientaddr;	
	int length = sizeof(clientaddr);	
	ULONG lngMode = 1;
	TMYOVERLAPPED * pOvrl = NULL;
	SOCKET listensocket, clientsocket;
	int blnBindLocal = 1;
	WORD port = 5001;

	m_stop = 0;

	/////////////////////////////
	GetSystemInfo(&si);
	/////////////////////////////
	

	if( (nRet = WSAStartup( MAKEWORD(2, 2), &wsData )) < 0 ) {
		return false;
	}

	if ( (listensocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) {
		return false;
	}
	
	memset(&addr, 0, sizeof(addr));
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	addr.sin_addr.s_addr = (blnBindLocal) ? inet_addr("127.0.0.1") : htonl(INADDR_ANY);	
	
	if ( (nRet = bind( listensocket, (struct sockaddr *) &addr, sizeof(addr) )) < 0 ) {
		closesocket (listensocket );
		return false;
	}
	
	if ( (nRet = listen( listensocket, 100 )) < 0 ) {
		closesocket (listensocket );
		return false;
	}	
	
	if ( (m_hIocp = ::CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 0, 0 )) == NULL ) {
		closesocket (listensocket );
		return false;
	}
	/////////////////////////////////////////////////////////////////////////////////////////

	threads = (si.dwNumberOfProcessors);

	for(i=0;i<(int)threads;i++) {

		TIOCPParams params;
		CWinThread * pThread = NULL;

		memset(&params, 0, sizeof(params));
		ResetEvent(m_threadEvent);		

		params.m_This = this;
		params.m_ThreadNumber = i;

		pThread = AfxBeginThread((AFX_THREADPROC)gIOCPThread, &params, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
			
		pThread->m_bAutoDelete = true;
		pThread->ResumeThread();
		
		Sleep(10);

		WaitForSingleObject(m_threadEvent, INFINITE);
	}	
	
	while( m_stop == 0 ) {

		pOvrl = new TMYOVERLAPPED();
		memset(pOvrl, 0, sizeof(*pOvrl));
		
		if ( (pOvrl->m_sock = accept(listensocket, (struct sockaddr *)&clientaddr, &length)) != INVALID_SOCKET ) {

			m_Mutex.Lock();
			m_opcnt++;
			m_Mutex.Unlock();
			
			printf("connection #%u\r\n", ++cnt);

			if (ioctlsocket(pOvrl->m_sock, FIONBIO, (u_long FAR*) &lngMode) == SOCKET_ERROR ) {					
				closesocket( pOvrl->m_sock );
				continue;
			}			

			//CreateIoCompletionPort( (HANDLE)pOvrl->m_sock, m_hIocp, (ULONG)&pOvrl->m_sock, 0 );		
			
			if ( pOvrl != NULL ) {			
				PostQueuedCompletionStatus(m_hIocp, 1, NULL, (OVERLAPPED*)pOvrl);
			}
		}		
	};	
	
	return true;
}

int CD2Class::Stop()
{	
	WSACleanup();
	CloseHandle(m_hIocp);

	Sleep(100);
	m_stop = 1;
	
	return true;
}

int CD2Class::IOCPThread(TIOCPParams * pParams)
{
	int nRet = 0, localstop = 0;
	void * pKey;
	TMYOVERLAPPED * pOvrl;
	DWORD dwBytesTransferred;
	DWORD error;
	TIOCPParams params = *pParams;

	SetEvent(m_threadEvent);
	Sleep(10);

	while ( ( m_stop == 0 ) && (localstop == 0) )
	{
		pKey = NULL;
		pOvrl = NULL;
		
		nRet = GetQueuedCompletionStatus(m_hIocp, &dwBytesTransferred, (ULONG*)&pKey, (OVERLAPPED **)&pOvrl, 5000);
		
		if(nRet == 0) {				
			
			error = GetLastError();
			if( error == WAIT_TIMEOUT ) {

				printf("thread #%u\r\n", params.m_ThreadNumber + 1);
				continue;
			}		
			
			if ( pOvrl == NULL )
				continue;
		}

		if (pOvrl->m_ovrl.hEvent != 0) {
			m_stop = m_stop;
		}

		//CloseHandle( (HANDLE)pOvrl->m_sock );
		closesocket( pOvrl->m_sock );
		delete pOvrl;
		
		m_Mutex.Lock();
		m_opcnt--;
		m_Mutex.Unlock();
	};
	
	return nRet;
}