最近發現我那簡單得不再簡單的IOCP+UDP的底層出錯了,在大數據量的時候經常會報錯,并且清一色都是報的:報0xC000000005,讀取0x00000010錯誤.報錯之后,整個程序的堆棧就全部破壞掉了.從發現問題到今日問題的解決,已經過去了一個月的時間.
唯一能夠找到相關的資料只有:
http://www.shnenglu.com/HendricLee/archive/2008/07/29/57436.html但是事實上,我的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的成員變量保存,這樣生命周期可以得以保證.
好吧,這件腦殘事就這么結了.