删除 ptr 将解决写入 0 的访问冲突异常
我得到以下代码,其中最后一条语句我尝试删除指向动态创建的内存的指针。
但是,一旦我到达指令,就会引发访问冲突异常,并显示:
0x0094c91f 处未处理的异常 Server.exe:0xC0000005:访问 违规读取位置 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;
};
编辑2:与向函数提供参数有关的线程代码...
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));
I got the following code in which last statement I try to delete a pointer to dynamically created memory.
But as soon as I get to the instruction a Access Violation exception is raised saying :
Unhandled exception at 0x0094c91f in
Server.exe: 0xC0000005: Access
violation reading location 0x00000000.
But when I step through it with the debugger it contains a valid address with valid data in it... I don't realize what I'm doing fatally wrong here...
Any suggestions?
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;
}
EDIT: I did allocate the memory in another function in the main thread
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: the threads code to do with giving the parameter to the function...
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));
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
抱歉,无法从您提供的零碎内容中真正弄清楚任何内容。
但是,在第三段代码中,您有此调用。
此调用将通过调用
delete
来销毁*pOverlapped
对象。 (请记住,在HandleAcceptRequest
的最后,您要删除 pRequest
,其中pRequest
是HandleAcceptRequest
的参数) 。这将使 pOverlapped 成为指向死内存的悬空指针。我在代码中没有看到任何地方可以重新初始化悬空指针或将其设置为空。
如果您不重新初始化它,则循环中对 *pOverlapped 的下一次访问将访问死内存(这可能看起来“有效”),并且下一次尝试删除< /code> 它很可能再次崩溃。如果下一次
删除
尝试再次发生在HandleAcceptRequest
末尾,那么行为可能与您最初描述的完全一样。Sorry, there's no way to really figure anything out from bits and pieces you provided.
However, in the third piece of code you have this call
This call will destroy the
*pOverlapped
object by callingdelete
on it. (Remember that at the very end ofHandleAcceptRequest
you dodelete pRequest
, wherepRequest
is the parameter ofHandleAcceptRequest
).This will make
pOverlapped
a dangling pointer that points to dead memory. I don't see any place in your code where you would re-initialize that dangling pointer or set it to null.If you don't re-initialize it, then the next access to
*pOverlapped
in the cycle will access dead memory (which might appear to "work") and the next attempt todelete
it again will most likely crash. If the nextdelete
attempt is the one at the end ofHandleAcceptRequest
again, then the behavior will probably be exactly as what you originally described.好的。看来您删除了错误的指针。您在 HandleAcceptRequest() 中删除的不再是指向 OVERLAPPED 的指针,因为该指针已从 OVERLAPPED* 转换为 ACCEPT_REQUEST*。
GetCompletionStatus() 是你自己的吗?
Ok. It seems you are deleting the wrong pointer. The one you are deleting inside HandleAcceptRequest() is no longer a pointer to an OVERLAPPED, since the pointer has been casted from OVERLAPPED* to ACCEPT_REQUEST*.
Is GetCompletionStatus() your own?