天天看點

IOCP+UDP收包的時候:報0xC000000005,讀取0x00000010錯誤的問題

最近發現我那簡單得不再簡單的IOCP+UDP的底層出錯了,在大資料量的時候經常會報錯,并且清一色都是報的:報0xC000000005,讀取0x00000010錯誤.報錯之後,整個程式的堆棧就全部破壞掉了.從發現問題到今日問題的解決,已經過去了一個月的時間.

但是事實上,我的Overlapped都是複用的.是以,不大可能是此問題導緻的.經過測試證明,也确實與此無關.

昨晚上又做了一系列的測試,結果到最後依舊是無果,百般無奈之下,隻好問人,後面QQ好友Sagasarate告訴了我原委,我知道之後,隻有兩種感覺:想哭,想撞牆.

IOCP+UDP收包的時候:報0xC000000005,讀取0x00000010錯誤的問題

至于為什麼,請看以下代碼便知了.非常非常之低級的錯誤.

bool CUDPRecvSendThread::postRecvRequest(CUdpOverLappedRecv* pOverLappedRecv)

IOCP+UDP收包的時候:報0xC000000005,讀取0x00000010錯誤的問題

{

IOCP+UDP收包的時候:報0xC000000005,讀取0x00000010錯誤的問題

    ASSERT(pOverLappedRecv);

IOCP+UDP收包的時候:報0xC000000005,讀取0x00000010錯誤的問題

    if (pOverLappedRecv == NULL) return false;

IOCP+UDP收包的時候:報0xC000000005,讀取0x00000010錯誤的問題
IOCP+UDP收包的時候:報0xC000000005,讀取0x00000010錯誤的問題

    pOverLappedRecv->Reset();

IOCP+UDP收包的時候:報0xC000000005,讀取0x00000010錯誤的問題
IOCP+UDP收包的時候:報0xC000000005,讀取0x00000010錯誤的問題

    DWORD dwBytesRecv = 0;

IOCP+UDP收包的時候:報0xC000000005,讀取0x00000010錯誤的問題

    DWORD dwFlags = 0;

IOCP+UDP收包的時候:報0xC000000005,讀取0x00000010錯誤的問題

    int nSenderAddrSize = sizeof (sockaddr_in);

IOCP+UDP收包的時候:報0xC000000005,讀取0x00000010錯誤的問題
IOCP+UDP收包的時候:報0xC000000005,讀取0x00000010錯誤的問題

    int rc = 0;

IOCP+UDP收包的時候:報0xC000000005,讀取0x00000010錯誤的問題

    rc = ::WSARecvFrom(m_ServerSocket, pOverLappedRecv->GetWsaBuffer(), 1, &dwBytesRecv, &dwFlags,

IOCP+UDP收包的時候:報0xC000000005,讀取0x00000010錯誤的問題

        pOverLappedRecv->GetClientAddr(), &nSenderAddrSize,

IOCP+UDP收包的時候:報0xC000000005,讀取0x00000010錯誤的問題

        pOverLappedRecv->GetOverlapped(), NULL);

IOCP+UDP收包的時候:報0xC000000005,讀取0x00000010錯誤的問題
IOCP+UDP收包的時候:報0xC000000005,讀取0x00000010錯誤的問題

    if (rc == SOCKET_ERROR)

IOCP+UDP收包的時候:報0xC000000005,讀取0x00000010錯誤的問題

    {

IOCP+UDP收包的時候:報0xC000000005,讀取0x00000010錯誤的問題

        DWORD dwErrorCode = ::WSAGetLastError();

IOCP+UDP收包的時候:報0xC000000005,讀取0x00000010錯誤的問題

        if (dwErrorCode != WSA_IO_PENDING)

IOCP+UDP收包的時候:報0xC000000005,讀取0x00000010錯誤的問題

        {

IOCP+UDP收包的時候:報0xC000000005,讀取0x00000010錯誤的問題

            return false;

IOCP+UDP收包的時候:報0xC000000005,讀取0x00000010錯誤的問題

        }

IOCP+UDP收包的時候:報0xC000000005,讀取0x00000010錯誤的問題

    }

IOCP+UDP收包的時候:報0xC000000005,讀取0x00000010錯誤的問題
IOCP+UDP收包的時候:報0xC000000005,讀取0x00000010錯誤的問題

    return true;

IOCP+UDP收包的時候:報0xC000000005,讀取0x00000010錯誤的問題

}

請對照着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的成員變量儲存,這樣生命周期可以得以保證.

好吧,這件腦殘事就這麼結了.

繼續閱讀