完成端口接收udp 在release模式下报内存访问冲突

ima_zhan 2019-09-12 11:05:06
在使用完成端口接收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. ";
}
}
...全文
469 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
xian_wwq 2019-11-07
  • 打赏
  • 举报
回复
1.多线程调试不能靠下断点,加日志输出 2.对pIoContext不能默认是有效的 8楼提到了 3. try...catch的范围太大了 不利于找错误
_mervyn 2019-10-16
  • 打赏
  • 举报
回复
引用 4 楼 ima_zhan 的回复:
[quote=引用 2 楼 Eleven 的回复:] Release下打点log出来,先定位一下问题所在的函数,检查一下指针是否有效,引用的内存是否被提前释放等~
就在iRcvNum++;那一行,看了下当时的数据也没发现问题,起码都是有效的,而且那个函数是在iocp的线程函数里直接引用的 [/quote] 我以前在用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,之前我就是疏忽,直接取了局部变量的地址传入。导致程序崩溃都不知道崩在哪。找了好久才注意到这个,修改之后,再也没崩溃过。。。
zgl7903 2019-09-12
  • 打赏
  • 举报
回复
条件判断充分, 用 __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);

走好每一步 2019-09-12
  • 打赏
  • 举报
回复
引用 楼主 ima_zhan 的回复:
在使用完成端口接收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(...) { }
走好每一步 2019-09-12
  • 打赏
  • 举报
回复
而且释放的行为也不一样。 有的释放了还在,还可以用,是随机行为。 有的释放了就没了,不可以用,访问就崩溃了。 仔细检查代码。这和你个人写代码的习惯有关系。 1、new内存后,是否memset 2、delete内存后,是否指针赋NULL,是否存在野指针 3、使用指针前,是否判断非空再使用。 4、编译器警告是否调成最高级别 5、strcpy是否废弃,使用strncpy这些,VS有大量的废弃函数,是否改用新的安全函数
走好每一步 2019-09-12
  • 打赏
  • 举报
回复
引用 3 楼 ima_zhan 的回复:
[quote=引用 1 楼 走好每一步 的回复:] 你代码问题,这种问题我遇到过。 Debug内存是有初始化的,Release没有。
内存初始化什么意思,申请的新的空间数据清零?[/quote] 就是debug下new的内存块和release下new的内存卡是有区别的。
ima_zhan 2019-09-12
  • 打赏
  • 举报
回复
引用 2 楼 Eleven 的回复:
Release下打点log出来,先定位一下问题所在的函数,检查一下指针是否有效,引用的内存是否被提前释放等~

就在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);
}
}
}
ima_zhan 2019-09-12
  • 打赏
  • 举报
回复
引用 1 楼 走好每一步 的回复:
你代码问题,这种问题我遇到过。
Debug内存是有初始化的,Release没有。

内存初始化什么意思,申请的新的空间数据清零?
Eleven 2019-09-12
  • 打赏
  • 举报
回复
Release下打点log出来,先定位一下问题所在的函数,检查一下指针是否有效,引用的内存是否被提前释放等~
走好每一步 2019-09-12
  • 打赏
  • 举报
回复
你代码问题,这种问题我遇到过。 Debug内存是有初始化的,Release没有。

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧