IOCP+UDP收包的時候:報0xC000000005,讀取0x00000010錯誤的問題
阿新 • • 發佈:2018-12-27
最近發現我那簡單得不再簡單的IOCP+UDP的底層出錯了,在大資料量的時候經常會報錯,並且清一色都是報的:報0xC000000005,讀取0x00000010錯誤.報錯之後,整個程式的堆疊就全部破壞掉了.從發現問題到今日問題的解決,已經過去了一個月的時間.
唯一能夠找到相關的資料只有:http://www.cppblog.com/HendricLee/archive/2008/07/29/57436.html
但是事實上,我的Overlapped都是複用的.因此,不大可能是此問題導致的.經過測試證明,也確實與此無關.
昨晚上又做了一系列的測試,結果到最後依舊是無果,百般無奈之下,只好問人,後面QQ好友Sagasarate告訴了我原委,我知道之後,只有兩種感覺:想哭,想撞牆.
至於為什麼,請看以下程式碼便知了.非常非常之低階的錯誤.
bool CUDPRecvSendThread::postRecvRequest(CUdpOverLappedRecv* pOverLappedRecv)
{
ASSERT(pOverLappedRecv);
if (pOverLappedRecv == NULL) returnfalse;
pOverLappedRecv->Reset();
DWORD dwBytesRecv =0;
DWORD dwFlags =0;
int nSenderAddrSize =sizeof (sockaddr_in);
int rc =0;
rc = ::WSARecvFrom(m_ServerSocket, pOverLappedRecv->GetWsaBuffer(), 1, &dwBytesRecv, &dwFlags,
pOverLappedRecv->GetClientAddr(), &nSenderAddrSize,
pOverLappedRecv->GetOverlapped(), NULL);
if (rc == SOCKET_ERROR)
{
DWORD dwErrorCode = ::WSAGetLastError();
if (dwErrorCode != WSA_IO_PENDING)
{
returnfalse;
}
}
returntrue;
}請對照著MSDN看.
如果沒看出來,那我來告訴你是為什麼.
問題就在於WSARecvFrom的7個引數.
MSDN的描述:
lpFromlen[in, out]
唯一能夠找到相關的資料只有:http://www.cppblog.com/HendricLee/archive/2008/07/29/57436.html
但是事實上,我的Overlapped都是複用的.因此,不大可能是此問題導致的.經過測試證明,也確實與此無關.
昨晚上又做了一系列的測試,結果到最後依舊是無果,百般無奈之下,只好問人,後面QQ好友Sagasarate告訴了我原委,我知道之後,只有兩種感覺:想哭,想撞牆.
至於為什麼,請看以下程式碼便知了.非常非常之低階的錯誤.
bool CUDPRecvSendThread::postRecvRequest(CUdpOverLappedRecv* pOverLappedRecv)
ASSERT(pOverLappedRecv);
if (pOverLappedRecv == NULL) returnfalse;
pOverLappedRecv->Reset();
DWORD dwBytesRecv =0;
DWORD dwFlags =0;
int nSenderAddrSize =sizeof (sockaddr_in);
int rc =0;
rc = ::WSARecvFrom(m_ServerSocket, pOverLappedRecv->GetWsaBuffer(), 1, &dwBytesRecv,
pOverLappedRecv->GetClientAddr(), &nSenderAddrSize,
pOverLappedRecv->GetOverlapped(), NULL);
if (rc == SOCKET_ERROR)
{
DWORD dwErrorCode = ::WSAGetLastError();
if (dwErrorCode != WSA_IO_PENDING)
{
returnfalse;
}
}
}請對照著MSDN看.
如果沒看出來,那我來告訴你是為什麼.
問題就在於WSARecvFrom的7個引數.
MSDN的描述:
A pointer to the size, in bytes, of the "from" buffer required only iflpFromis specified.
你會發現,這個引數是一個輸入輸出值.而WSARecvFrom投遞的是一個非同步的IOCP請求,故而,出了此方法(CUDPRecvSendThread::postRecvRequest)之後,nSenderAddrSize這個臨時變數就會被回收.不出事才怪了.
好吧,這事就是我幹出來的.今年竟是做一些腦殘的事情.腫麼了我這是.T_T
要解決這個問題,最好的辦法就是把nSenderAddrSize作為CUdpOverLappedRecv的成員變數儲存,這樣生命週期可以得以保證.
好吧,這件腦殘事就這麼結了.
posted on 2012-10-15 11:42 楊粼波 閱讀(1641) 評論(8) 編輯 收藏 引用 所屬分類: 原創文章 、網路程式設計 、C++ 、Windows