最近發現我那簡單得不再簡單的IOCP+UDP的底層出錯了,在大資料量的時候經常會報錯,并且清一色都是報的:報0xC000000005,讀取0x00000010錯誤.報錯之後,整個程式的堆棧就全部破壞掉了.從發現問題到今日問題的解決,已經過去了一個月的時間.
但是事實上,我的Overlapped都是複用的.是以,不大可能是此問題導緻的.經過測試證明,也确實與此無關.
昨晚上又做了一系列的測試,結果到最後依舊是無果,百般無奈之下,隻好問人,後面QQ好友Sagasarate告訴了我原委,我知道之後,隻有兩種感覺:想哭,想撞牆.

至于為什麼,請看以下代碼便知了.非常非常之低級的錯誤.
bool CUDPRecvSendThread::postRecvRequest(CUdpOverLappedRecv* pOverLappedRecv)
{
ASSERT(pOverLappedRecv);
if (pOverLappedRecv == NULL) return false;
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)
{
return false;
}
}
return true;
}
請對照着MSDN看.
如果沒看出來,那我來告訴你是為什麼.
問題就在于WSARecvFrom的7個參數.
MSDN的描述:
lpFromlen [in, out]
A pointer to the size, in bytes, of the "from" buffer required only if lpFrom is specified.
你會發現,這個參數是一個輸入輸出值.而WSARecvFrom投遞的是一個異步的IOCP請求,故而,出了此方法(CUDPRecvSendThread::postRecvRequest)之後,nSenderAddrSize這個臨時變量就會被回收.不出事才怪了.
好吧,這事就是我幹出來的.今年竟是做一些腦殘的事情.腫麼了我這是.T_T
要解決這個問題,最好的辦法就是把nSenderAddrSize作為CUdpOverLappedRecv的成員變量儲存,這樣生命周期可以得以保證.
好吧,這件腦殘事就這麼結了.