2011-03-21 8 views
-3

다음 문장에서 나는 동적으로 생성 된 메모리에 대한 포인터를 삭제하려고합니다.ptr이 0에 쓰는 액세스 위반 예외에서 해결됨

하지만 곧 나는 액세스 위반 예외가 말하는 발생의 지시에 도착 같이가 0xc0000005 : SERVER.EXE에서 0x0094c91f에서

처리되지 않은 예외 액세스 위치를 0x00000000을 읽는 위반.

하지만 디버거로 단계별 때 거기에 유효한 데이터와 유효 주소를 포함 ... 내가 ... 내가 잘못 여기에 치명적 뭘하는지

어떤 제안을 실현하지 않습니다 ?

void CServer::HandleAcceptRequest(ACCEPT_REQUEST* pRequest) 
{ 
    //Add the new connection socket to the connection handler 
    m_pConnectionHandler->AddConnection(pRequest->m_NewConnection); 
    //Associate the new connections´ socket handle with the IOCP 
    if(!m_pCompletionPort->AssociateHandle((HANDLE)pRequest->m_NewConnection, 0)) 
    { 
     MessageBox(NULL, "Could not associate a socket handle with the completion port", "", MB_ICONERROR | MB_OK); 
     DebugBreak(); 
    } 


    //Create a new COMM_REQUEST and initialize a Recv-Request 
    COMM_REQUEST* pCommRequest = new COMM_REQUEST; 
    memset(pCommRequest, 0, sizeof(COMM_REQUEST)); 
    pCommRequest->Socket = pRequest->m_NewConnection; 
    pCommRequest->m_RequestType = BASIC_REQUEST::RECV; 

    WSABUF* buf = new WSABUF; 
    buf->buf = pCommRequest->cBuf; 
    buf->len = Inc::COMMUNICATION_BUFFER_SIZE; 
    DWORD dwFlags = 0; 
    if(WSARecv(pCommRequest->Socket, buf, 1, NULL, &dwFlags, pCommRequest, NULL)) 
    { 
     DWORD dwRet = WSAGetLastError(); 
     if(dwRet != WSA_IO_PENDING) 
     { 
      MessageBox(NULL, "WSARecv() failed", "", MB_ICONERROR | MB_OK); 
      DebugBreak(); 
     } 
    }; 

    //Delete the old ACCEPT_REQUEST structure 
    delete pRequest; 
} 

편집 : 나는 메인 스레드에서

bool CConnectionHandler::AcceptNewConnection(SOCKET ListenSocket, unsigned nCount) 
{ 
    DWORD dwBytesReceived = 0; 
    ACCEPT_REQUEST* pOverlapped = nullptr; 

    for(unsigned n = 0; n < nCount; n++) 
    { 
     dwBytesReceived = 0; 
     pOverlapped = new ACCEPT_REQUEST; 
     memset(pOverlapped, 0, sizeof(ACCEPT_REQUEST)); 
     pOverlapped->m_RequestType = ACCEPT_REQUEST::ACCEPT; 

     //add the ListenSocket to the request 
     pOverlapped->m_ListenSocket = ListenSocket; 
     //invalidate the new connection socket 
     pOverlapped->m_NewConnection = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
     if(pOverlapped->m_NewConnection == INVALID_SOCKET) 
     { 
      delete pOverlapped; 
      return false; 
     } 

     // call 'AcceptEx' 
     if(m_lpfnAcceptEx(pOverlapped->m_ListenSocket, pOverlapped->m_NewConnection, pOverlapped->cOutputBuffer, 0, sizeof(sockaddr_in) + 16, sizeof(sockaddr_in) + 16, &dwBytesReceived, pOverlapped) == FALSE) 
     { 
      DWORD dwRet = WSAGetLastError(); 
      if(dwRet == ERROR_IO_PENDING) 
       continue; 
      else 
       return false; 
     } 
    } 

    return true; 
}; 

EDIT2 다른 함수의 메모리를 할당 한 : 함수에 매개 변수를 제공과 함께 할 수있는 스레드 코드를 ...

unsigned int WINAPI ServerThreadFunc(void* pvArgs) 
{ 
    CServer* pServer = (CServer*)pvArgs;  // pointer to the server object 
    DWORD dwBytes = 0; 
    ULONG_PTR ulKey; 
    OVERLAPPED* pOverlapped = nullptr; 
    bool bLooping = true; 

    while(bLooping) 
    { 
     //TODO: Add code (ServerThreadFunc) 
     if(!pServer->m_pCompletionPort->GetCompletionStatus(&dwBytes, &ulKey, &pOverlapped, INFINITE)) 
     { 
      //TODO: Set some error variable or flag an error event to notify the main thread 
      DebugBreak(); 
     } 

     //check type of request 
     switch(((BASIC_REQUEST*)pOverlapped)->m_RequestType) 
     { 
     case BASIC_REQUEST::ACCEPT: 
      { 
       // TODO: Handle AcceptEx-request 
       pServer->HandleAcceptRequest(static_cast<ACCEPT_REQUEST*>(pOverlapped)); 
+1

어디에서 메모리를 할당 했습니까? – sth

+1

pRequest는 어디에서 왔습니까? 그것은 단지 코드에 환영받지 못한 손님처럼 나타납니다! :) – ralphtheninja

+0

두 기능을 모두 추가했습니다. – Incubbus

답변

1

죄송합니다. 제공된 비트와 조각을 실제로 알아낼 수있는 방법은 없습니다.

그러나, 코드의 세 번째 부분에서 당신은이 호출 그것에 delete를 호출하여 *pOverlapped 오브젝트를 파괴이 호출

pServer->HandleAcceptRequest(static_cast<ACCEPT_REQUEST*>(pOverlapped)); 

있습니다. HandleAcceptRequest의 마지막 부분에 delete pRequest을 입력하십시오. pRequestHandleAcceptRequest의 매개 변수입니다.

이렇게하면 pOverlapped이 불량 메모리를 가리키는 매달려 포인터가됩니다. 나는 그 매달려있는 포인터를 다시 초기화하거나 null로 설정하는 코드에서 어떤 위치도 보지 못합니다.

다시 초기화하지 않으면 순환에서 *pOverlapped에 대한 다음 액세스가 (작동하는 것처럼 보이는) 불량 메모리에 액세스하고 다시 delete에 대한 다음 시도가 충돌 할 가능성이 높습니다. 다음 delete 시도가 HandleAcceptRequest 끝에있는 시도 인 경우 동작은 원래 설명했던 것과 동일합니다.

+0

왜이 전화를 "삭제"합니까? – Incubbus

+2

@Incubbus : 당신이'HandleAcceptRequest'의 마지막에'delete'를 호출하기 때문입니다. 네가 묻는 바로 그 '삭제'가 기억 나니? – AnT

+1

안녕하세요! 나는 웹 서버 다! http://xkcd.com/869/;) – ralphtheninja

0
OVERLAPPED* pOverlapped = nullptr; 
.. 
pServer->m_pCompletionPort->GetCompletionStatus(&dwBytes, &ulKey, &pOverlapped, INFINITE); 

확인. 잘못된 포인터를 삭제하는 것 같습니다. 포인터가 OVERLAPPED *에서 ACCEPT_REQUEST *로 형 변환 되었기 때문에 HandleAcceptRequest()에서 삭제하려는 포인터는 더 이상 OVERLAPPED에 대한 포인터가 아닙니다.

GetCompletionStatus()는 나만의 것이니까?