在使用完成埠接收udp資料時,debug模式下正常,但是在release模式下報記憶體訪問沖突的錯誤,資料長度也沒超過快取大小
接收函式如下:
// 處理接收的udp資料
void tagPER_SOCK_CONTEXT::DoRecvUdp(PER_IO_CONTEXT* pIoContext,
DWORD dwLen, int iThreadId) {
try {
EnterCriticalSection(&rcvUdpDataIocpSection);
iRcvNum++;
if (this->rcvDataHandler)
(*(this->rcvDataHandler))(this->clientData,
(unsigned char*)pIoContext->m_szBuffer, dwLen, pIoContext->addr, 0);
bool brst = this->PostRecvUdp(pIoContext, iThreadId);
LeaveCriticalSection(&rcvUdpDataIocpSection);
}
catch (...) {
//std::cout << "catch erro. ";
}
}
uj5u.com熱心網友回復:
你代碼問題,這種問題我遇到過。Debug記憶體是有初始化的,Release沒有。
uj5u.com熱心網友回復:
Release下打點log出來,先定位一下問題所在的函式,檢查一下指標是否有效,參考的記憶體是否被提前釋放等~uj5u.com熱心網友回復:
記憶體初始化什么意思,申請的新的空間資料清零?
uj5u.com熱心網友回復:
就在iRcvNum++;那一行,看了下當時的資料也沒發現問題,起碼都是有效的,而且那個函式是在iocp的執行緒函式里直接參考的
BOOL bReturn = GetQueuedCompletionStatus(svrInfo->m_hIOCompletionPort, &dwBytesTransferred, (PULONG_PTR)&pSocketContext, &pOverLapped, INFINITE);
if (!bReturn) {
DWORD dErr = GetLastError();
PER_IO_CONTEXT *pIoContext = CONTAINING_RECORD(pOverLapped, PER_IO_CONTEXT, overLapped);
svrInfo->HandleQueueCompletionErr(pSocketContext, pIoContext, dErr);
}
else {
PER_IO_CONTEXT *pIoContext = CONTAINING_RECORD(pOverLapped, PER_IO_CONTEXT, overLapped);
switch (pIoContext->opType)
{
case RECVUDP_POST:
if (pSocketContext) {
pSocketContext->DoRecvUdp(pIoContext, dwBytesTransferred, iThreadId);
}
}
}
uj5u.com熱心網友回復:
就是debug下new的記憶體塊和release下new的記憶體卡是有區別的。
uj5u.com熱心網友回復:
而且釋放的行為也不一樣。有的釋放了還在,還可以用,是隨機行為。
有的釋放了就沒了,不可以用,訪問就崩潰了。
仔細檢查代碼。這和你個人寫代碼的習慣有關系。
1、new記憶體后,是否memset
2、delete記憶體后,是否指標賦NULL,是否存在野指標
3、使用指標前,是否判斷非空再使用。
4、編譯器警告是否調成最高級別
5、strcpy是否廢棄,使用strncpy這些,VS有大量的廢棄函式,是否改用新的安全函式
uj5u.com熱心網友回復:
在使用完成埠接收udp資料時,debug模式下正常,但是在release模式下報記憶體訪問沖突的錯誤,資料長度也沒超過快取大小
接收函式如下:
// 處理接收的udp資料
void tagPER_SOCK_CONTEXT::DoRecvUdp(PER_IO_CONTEXT* pIoContext,
DWORD dwLen, int iThreadId) {
try {
EnterCriticalSection(&rcvUdpDataIocpSection);
iRcvNum++;
if (this->rcvDataHandler)
(*(this->rcvDataHandler))(this->clientData,
(unsigned char*)pIoContext->m_szBuffer, dwLen, pIoContext->addr, 0);
bool brst = this->PostRecvUdp(pIoContext, iThreadId);
LeaveCriticalSection(&rcvUdpDataIocpSection);
}
catch (...) {
//std::cout << "catch erro. ";
}
}
這個代碼是有很致命的問題的,
EnterCriticalSection和LeaveCriticalSection成對使用時,中間不能有return,不能有例外!!!!!!
不然就會出現死鎖!!!!!!!!!!!!!
你要么自己寫一個CLock,要么使用boost,或者c++11里的lockguard
try
{
CLock lock; //自動物件鎖,創建時上鎖,物件銷毀時自動解鎖
}
catch(...)
{
}
uj5u.com熱心網友回復:
條件判斷充分, 用 __try __except 捕捉SEH例外
EnterCriticalSection(&rcvUdpDataIocpSection);
iRcvNum++;
__try
{
if (rcvDataHandler
&& pIoContext
&& pIoContext->m_szBuffer
&& //條件要判斷充分
&& 1)
{
(*(this->rcvDataHandler))(this->clientData,
(unsigned char*)pIoContext->m_szBuffer, dwLen, pIoContext->addr, 0);
}
bool brst = this->PostRecvUdp(pIoContext, iThreadId);
}
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
{
ASSERT(FALSE);
}
LeaveCriticalSection(&rcvUdpDataIocpSection);
uj5u.com熱心網友回復:
Release下打點log出來,先定位一下問題所在的函式,檢查一下指標是否有效,參考的記憶體是否被提前釋放等~
就在iRcvNum++;那一行,看了下當時的資料也沒發現問題,起碼都是有效的,而且那個函式是在iocp的執行緒函式里直接參考的
我以前在用WSARecvFrom異步接收udp資料時有一個疏忽,找了很久才找到的。雖然不知道你的問題是否也會一樣,我也提一下,僅供參考。
int WSARecvFrom(
__in SOCKET s,
__in_out LPWSABUF lpBuffers,
__in DWORD dwBufferCount,
__out LPDWORD lpNumberOfBytesRecvd,
__in_out LPDWORD lpFlags,
__out struct sockaddr* lpFrom,
__in_out LPINT lpFromlen,
__in LPWSAOVERLAPPED lpOverlapped,
__in LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
這個函式第6、7兩個引數(lpFrom,lpFromlen),在資料接收完成前,不能被銷毀。 尤其注意第7個引數!也就是lpFromlen,之前我就是疏忽,直接取了區域變數的地址傳入。導致程式崩潰都不知道崩在哪。找了好久才注意到這個,修改之后,再也沒崩潰過。。。
uj5u.com熱心網友回復:
1.多執行緒除錯不能靠下斷點,加日志輸出2.對pIoContext不能默認是有效的
8樓提到了
3. try...catch的范圍太大了
不利于找錯誤
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/30264.html
標籤:網絡編程
