DEBUG版本通常是项目处理调试阶段的一种过渡版本,它跟本地的环境变量设置相关,并且能进行调试(如单步、断点等),一般来说它是不经过优化的,所以运行速度上不占优势。而RELEASE版本为了速度上和代码大小上都会作出一定的优化,所以两者区别还是蛮大的。
下面以一个多线程程序为例来讲解两者的区别。
线程1:
UINT CTCP_viewDlg::ThreadTcpFun(LPVOID lpParam)
{
CTCP_viewDlg *dlg = (CTCP_viewDlg *)lpParam;
dlg->ReceiveTcpRun();
return 0;
}
void CTCP_viewDlg::ReceiveTcpRun()
{
while(1)
{
if(true == begin_rev)
{
Tcp_Receive();
}
}
}
void CTCP_viewDlg::RunTcpReceive() //线程函数声明
{
CWinThread* pThread;
pThread = AfxBeginThread(ThreadTcpFun, (void *)this);
}
线程2:(按钮消息处理)
void CTCP_viewDlg::OnBnClickedConnect()
{
// TODO: 在此添加控件通知处理程序代码
CEdit* Ip = ((CEdit*)GetDlgItem(IDC_IP));
Ip->GetWindowText(ip_addr);
TcpInit(ip_addr);//初始化
begin_rev = true;
drawimage(image.GetImage(),IDC_IMAGE); //绘出图像到工作区
}
当处理按钮的主线程触发,begin_rev变量被置为真,这里将使线程1执行Tcp_Receive()函数,而这个函数是用于接收TCP数据的,它是一个死循环一直在接收着。
在DEBUG版本上,以上代码是能正常运行的,而放在RELEASE版本上以上代码则不能正常运行,这是为什么呢?
因为在DEBUG版本上, begin_rev变量并没有被编译器进行优化,所以当按钮点击后,使其置为真后能让线程1“检查”出来,所以线程1可以正常的进入到接收函数里。而当程序被发行时,编译器会对代码进行优化,此时 begin_rev变量在线程1里
if(true == begin_rev)
{
Tcp_Receive();
}
begin_rev变量被优化成只判断一次(在线程开始的时候),以后便不再判断此变量的真假,所以发行版本上Tcp_Receive()函数是不会被执行到的。
那么如何解决这个问题呢? 我们可以利用一个关键词volatile,这个关键词如何读者用过单片机会清楚,它被用于在中断处理程序里,让编译器不优化变量的,而此处它也同样适用,在声明变量前加入这个关键词便可将问题解决。
如果遇到程序在DEBUG版本上运行正常,而在发行版本运行不正常里,通常应该想到编译器优化这一点来,然后对代码进行查看,是否与以上所描述情况相近,如果是则可以参考这种做法来进行解决,这也是十分简便的做法。