把之前用VC6写的MFC工程升级到VC2005后,编译运行就崩溃,莫名其妙,问了ZV说是经常出现这种问题,要重新建立个工程拖代码才行,那好吧,就重来,折腾了好久,还是……又崩溃了……
这下头大了,同样的代码,VC6里正常,VC2005反而崩溃?尝试关闭连接的多种选项,除了出现莫名其妙的LNK ERROR以外一无所获,最后F8逐步调试,发现在_beginthread后的WaitForSingleObject处崩溃了,这么神奇?注释掉WaitForSingleObject,依然崩溃,在群里讨论半天也没可行结果,后来尝试去掉多线程,直接调用过程,太牛逼了,这下运行完好!
想想可能引起崩溃的原因有很多,比较容易接受的是多线程时传参丢失,因为在VC2005即时显示当前数据内容里看到似乎有点数据不太正确,但是经过一番折腾后问题依旧,用afxMessageBox弹出来却又是正常的数据,头都大了!
然后想到把参数写成固定的看看……依然崩溃,天啊!
折腾了一晚上都没结果,头都晕了,明天还有事情做,只好睡觉。
今晚忙完回来,不服,继续开VC8折腾!想想是不是_beginthread得改改,写成CreateThread,直接报错:
错误 4 error C2664: “CreateThread”: 不能将参数 3 从“DWORD (__stdcall *)(LPVOID *)”转换为“LPTHREAD_START_ROUTINE”
写成_beginthreadex,嗯,不报错了好像……
hThread=(HANDLE)_beginthreadex(NULL,0,(PBEGINTHREADEX_THREADFUNC)StressThread,(LPVOID)thread_info,0, (PBEGINTHREADEX_THREADID)&dwThreadID);
满怀信心运行,依然崩溃!!!!!
今晚比昨晚有耐心,慢慢跟语句,终于到这里的时候:
if(sendto(nSocket,request,strlen(request),0,NULL,0)==SOCKET_ERROR){
::AfxGetMainWnd()->SetWindowText(dlgTitle + " - 发送数据失败!");
}else{
lngPacketSent++;
CString szPacketSent;
szPacketSent.Format("已请求 %d 个连接",lngPacketSent);
::AfxGetMainWnd()->SetWindowText(dlgTitle + " - " + szPacketSent);
}
突然崩溃了!
突然有个念头,把
CString szPacketSent;
szPacketSent.Format("已请求 %d 个连接",lngPacketSent);
::AfxGetMainWnd()->SetWindowText(dlgTitle + " - " + szPacketSent);
全注释掉!再次运行,居然平安无事……
点停止……又崩溃了……
停止的代码是这个:
void CWebStressMFCDlg::OnBnClickedbtnattack()
{
CString sBtnText;
m_btnAttack.GetWindowText(sBtnText);
if(sBtnText=="开始(&S)"){
m_btnAttack.SetWindowText("停止(&S)");
char szBuffer[1024];
m_txtTarget.GetLine(0,szBuffer,1024);
Target=(char *)szBuffer;
bAttacking = true;
dwThreadNum=0;
dwThreadID=0;
lngPacketSent = 0;
::AfxGetMainWnd()->SetWindowText(dlgTitle + " - 正在初始化");
this->StartAttack();
}else{
m_btnAttack.SetWindowText("开始(&S)");
bAttacking = false;
dwThreadNum=0;
dwThreadID=0;
lngPacketSent = 0;
::AfxGetMainWnd()->SetWindowText(dlgTitle + " - 已停止");
}
}
这里的相同点只有一个,那就是::AfxGetMainWnd()->SetWindowText,难道是这个语句出问题?太天方夜谭了吧!但是尝试将它屏蔽后却再也没崩溃过!
事情开始有点眉目了,似乎是开始多线程以后再调用::AfxGetMainWnd()->SetWindowText就会发生崩溃,但是为啥之前VC6里死活没问题?找了半天资料没答案,最后很幸运的在某个站点看到一个全英文回答:
If AfxGetMainWnd is called from the application's primary thread, it returns the application's main window according to the above rules. If the function is called from a secondary thread in the application, the function returns the main window associated with the thread that made the call.
在多线程里调用AfxGetMainWnd返回的是与线程有关联的主窗体?但是我这程序只有一个窗体,但是它仍然崩溃,差不多明白了,多线程里获得的句柄不等于真正的窗体句柄,对这个句柄进行“非法写操作”,于是崩溃了……
了解了症状就好办了,在全局里写一个窗口句柄类变量
CWnd* m_pCWnd;
然后在初始化过程OnInitDialog里加上
m_pCWnd = AfxGetMainWnd();
以后要写窗体标题的时候就用m_pCWnd->SetWindowText,将程序里所有AfxGetMainWnd改为m_pCWnd,重新编译运行,终于不再崩溃了!
http://www.xue163.com/114/6/1141080.html