碰上灵异事件了? 请高手帮忙~~

jingtan 2009-08-16 11:53:59
一段在debug版下正常,但在release版下会偶然出现异常的代码.


bool MyNetMsgReceiver::onRecviveUdpMsg(UdpSocket* sock, char* msg, int length, sockaddr_in* fromAddr)
{
//DWORD temp[16] = {0};
ULONG data = sock->getUserData();
if (!data) return true;

if ((DWORD)msg < 0x1000)
{
__asm int 3h; //在这里的时候msg的值还是正常的
}

IMAccount* acc = g_ImAccMgr.getAccountObject(data);

if ((DWORD)msg < 0x1000)
{
__asm int 3h; //程序停在这里,此时mag的值被修改为0x10, 变成了一个错的指针
}

if (acc)
{
acc->handleUdpPacket(sock, msg, length, fromAddr);
}

return true;
}

//g_ImAccMgr.getAccountObject() 的代码


IMAccount* IMAccountMgr::getAccountObject(size_t objId)
{

IMAccount* acc = NULL;

EnterCriticalSection(&mCs);
AccountIter it = tbl.begin();
for (; it != tbl.end(); ++it)
if ((*it)->getObjeciId() == objId)
{
acc = (*it);
break;
}

LeaveCriticalSection(&mCs);
return acc;
}


是个随机性的错误, 程序运行几分到半个小时后才会触发 int 3h挺下来.
开始我以为是哪里的指针或数据越界了. 于是在函数里面加了个 DWORD temp[16]={0};

但是 msg 还是被准确的改为0x10了, 其他参数都没问题.

这段代码逻辑简单, 其他线程就算出错也不会修改到线程堆栈里面的内容.
真搞不懂了..
...全文
302 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
jingtan 2009-08-18
  • 打赏
  • 举报
回复
按上面修改多次后仍然报错. 另外还发现了新情况:
1, debug 也可能报错.
2, 修改代码后线程会在其他地方异常, 不局限在开始那个函数了.

查看进程里的线程状态, 除了系统线程, 就剩下主线程和这个子线程了. 主线程一直在等待窗口消息, 和子线程交互并不多, 应该也没什么没问题.

更奇怪的是, 增加了一些功能代码后, 程序居然不报错了...
FancyMouse 2009-08-17
  • 打赏
  • 举报
回复
光声明一个数组不用的话release里的优化会直接忽视掉,乃加了等于白加
flameearth 2009-08-17
  • 打赏
  • 举报
回复
doSend中

应该
看看可以不
INT iSendTotal = sendBytes;
do
{
int iSend = WSASend(....);
iSendTotal -= iSend;
if( iSendTotal <= 0 )
{ break; }
}while(TRUE)
dongming1011 2009-08-16
  • 打赏
  • 举报
回复
嗯,蛮有意思的。
lzy0001sl 2009-08-16
  • 打赏
  • 举报
回复
这个值得关注
fallening 2009-08-16
  • 打赏
  • 举报
回复
被别的线程修改了?
加个锁定看看?
Sou2012 2009-08-16
  • 打赏
  • 举报
回复
帮顶!!
jingtan 2009-08-16
  • 打赏
  • 举报
回复
修改编译选项后一段时间, 程序还是报错了.
这次跳到了acc->handleUdpPacket()函数里面, 值还是0x10....
于是查查哪里有0x10的地方, 通过排查发现: 同一线程下的另一组函数中有调用WSASend()函数发送数据,每次发送的长度就是0x10. 调用代码如下:

bool Connection::doSend()
{
if(sendBuf[0]->empty()) return false;

sendWsaBuf.buf = (char*)sendBuf[0]->c_str();
sendWsaBuf.len = sendBuf[0]->size();

DWORD sendBytes;

isSending = true;
int ret = WSASend(socket, &sendWsaBuf, 1, &sendBytes, 0, &sendOverLapped, sendResult);

if (ret == SOCKET_ERROR)
{
int error = WSAGetLastError();
if(error != WSA_IO_PENDING)
{//
isSending = false;
disConnect();
return false;
}
}
return true;
}


我这里使用重叠I/O模型,由于是非阻塞模式, 所以WSASend()是立即返回的. 执行完WSASend()后调用WSAWaitForMultipleEvents()函数等待结果, 前面的MyNetMsgReceiver::onRecviveUdpMsg()函数就是接收网络数据后系统回调函数调用的.

是不是这个sendBytes 变量的原因? 当程序调用EnterCriticalSection()后,线程被暂停, 如果此时数据发送完毕, 那这个sendBytes 变量会不会被系统自动更新?

现在把这个 sendBytes 变量改成了全局变量, 程序正常运行了1个多小时, 继续观察ing..
zgjxwl 2009-08-16
  • 打赏
  • 举报
回复
关注。。
logiciel 2009-08-16
  • 打赏
  • 举报
回复
试一下用C语句代替"__asm int 3h".
flameearth 2009-08-16
  • 打赏
  • 举报
回复
你是不是 release下没有使用多线程模式啊,以前我也遇到过这样的奇怪的问题,就是多线程的程序用了single thread 运行的 结果运行一会 就出问题了~
liuhaifeng1976 2009-08-16
  • 打赏
  • 举报
回复
机器的问题?
liuhaifeng1976 2009-08-16
  • 打赏
  • 举报
回复
DING
赵Andy 2009-08-16
  • 打赏
  • 举报
回复
往上挑挑
zbihong 2009-08-16
  • 打赏
  • 举报
回复
帮顶!
jingtan 2009-08-16
  • 打赏
  • 举报
回复
根据上面的思路修改代码, 还是出错!
比对debug版, 把编译选项 运行时基本检查 设置为:两者(/RTC1,等同于 /RTCsu)

目前为止还没报错, 晕死..
jingtan 2009-08-16
  • 打赏
  • 举报
回复
我把 参数msg去掉, 用其他方法取得msg地址, 发现sock也被改成了0x10. 这说明:

修改代码在onRecviveUdpMsg()函数外, 由另外的线程执行. 因为如果在同一线程,且在onRecviveUdpMsg()函数内部执行, 那么被修改的应该是length参数, 因为栈内寻址一般都是 基地址+ 偏移地址 这样的形式.
而onRecviveUdpMsg()函数上层的代码此时又没执行的机会.

联想到debug版不出现错误, 是不是由于debug版本下线程堆栈地址和release版不一样, 修改代码没修改到参数,所以程序没出现异常呢?
lovesnow1314 2009-08-16
  • 打赏
  • 举报
回复
监视一下内存,看看那个地址是在什么地方被修改的。
lgccaa 2009-08-16
  • 打赏
  • 举报
回复
碰到过随机错误的,很让人摸不着头脑,这种东西更多的是要靠大量的调试和环境测试

当然解决了的应当分享一下经验

64,637

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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