最近發(fā)現(xiàn)我那簡(jiǎn)單得不再簡(jiǎn)單的IOCP+UDP的底層出錯(cuò)了,在大數(shù)據(jù)量的時(shí)候經(jīng)常會(huì)報(bào)錯(cuò),并且清一色都是報(bào)的:報(bào)0xC000000005,讀取0x00000010錯(cuò)誤.報(bào)錯(cuò)之后,整個(gè)程序的堆棧就全部破壞掉了.從發(fā)現(xiàn)問(wèn)題到今日問(wèn)題的解決,已經(jīng)過(guò)去了一個(gè)月的時(shí)間.
唯一能夠找到相關(guān)的資料只有:
http://www.shnenglu.com/HendricLee/archive/2008/07/29/57436.html但是事實(shí)上,我的Overlapped都是復(fù)用的.因此,不大可能是此問(wèn)題導(dǎo)致的.經(jīng)過(guò)測(cè)試證明,也確實(shí)與此無(wú)關(guān).
昨晚上又做了一系列的測(cè)試,結(jié)果到最后依舊是無(wú)果,百般無(wú)奈之下,只好問(wèn)人,后面QQ好友Sagasarate告訴了我原委,我知道之后,只有兩種感覺(jué):想哭,想撞墻.

至于為什么,請(qǐng)看以下代碼便知了.非常非常之低級(jí)的錯(cuò)誤.
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;
} 請(qǐng)對(duì)照著MSDN看.
如果沒(méi)看出來(lái),那我來(lái)告訴你是為什么.
問(wèn)題就在于WSARecvFrom的7個(gè)參數(shù).
MSDN的描述:
lpFromlen [in, out]
A pointer to the size, in bytes, of the "from" buffer required only if lpFrom is specified.
你會(huì)發(fā)現(xiàn),這個(gè)參數(shù)是一個(gè)輸入輸出值.而WSARecvFrom投遞的是一個(gè)異步的IOCP請(qǐng)求,故而,出了此方法(CUDPRecvSendThread::postRecvRequest)之后,nSenderAddrSize這個(gè)臨時(shí)變量就會(huì)被回收.不出事才怪了.
好吧,這事就是我干出來(lái)的.今年竟是做一些腦殘的事情.腫么了我這是.T_T
要解決這個(gè)問(wèn)題,最好的辦法就是把nSenderAddrSize作為CUdpOverLappedRecv的成員變量保存,這樣生命周期可以得以保證.
好吧,這件腦殘事就這么結(jié)了.