我遇到了三个问题:
1. 程序在debug版本中正常运行和终止,但在release版本中进行QA时无法正常执行或终止。 经过对release版本的调试,我们发现代码优化没有问题。我关闭了Release版本选项,问题就解决了。
2.当遇到正常代码时,release版本会产生错误。经过调试,我们发现一些API调用没有检索到正确的值,一些变量无效,或者变量很难找到,所以我们修复了发布编译。例如,您可以将发布选项一一更改为相应的调试选项(例如,/MD 更改为/MDd、/O1 更改为/Od 等),也可以从运行时优化更改为程序大小优化。这样,目标机器上的release版本在执行过程中就不会遇到任何错误。
3. 即使在调试版本中,程序也有问题,但是当我在QA 目标计算机上运行发布版本时,出现以下错误:
此类问题通常是由于目标机没有VC执行环境造成的。然而,经过长时间的调查,mfcm90.dll问题仍然存在。使用Dependency Walker,我发现这个错误出现在msvcr90d.dll和msvcp90d.dll的调试版本中,这些版本都已发布。并且dll最终改变了项目配置中的运行时库选择/MD问题。
1、debug编译方式与release编译方式的本质区别
调试通常称为调试版本。它包含调试信息并且不执行优化,使程序员更容易调试他们的程序。发布版称为发布版本,通常包括各种优化,以在代码大小和执行速度方面优化程序,以便于用户使用。
调试和发布的真正秘诀是一组编译选项。两个选项如下所示
(当然还有其他的,例如/Fd /Fo,但区别并不重要。它们通常不会在发行版本中引起错误,因此这里不讨论它们。)
调试版本:
/MDd /MLd 或/MTd 使用调试运行时库(运行时函数库的调试版本)。
/Od 关闭优化开关
/D \”_DEBUG\” 相当于#define _DEBUG 并打开编译和调试代码(主要是
断言函数)
/ZI 创建编辑并继续数据库。调试后会出现这样的情况
如果在此过程中源代码发生变化,则无需重新编译。
/GZ 帮助检测内存错误
/Gm 打开最小化重新链接开关以减少链接时间
发布版本:
/MD /ML 或/MT 使用运行时库的发布版本
/O1 或/O2 优化开关使您的程序最小或最快
/D \”NDEBUG\” 关闭条件编译和调试代码开关(即不编译assert函数)。
/GF 合并重复的字符串并将它们放入只读内存中,以防止字符串常量被修改。
事实上,调试和发布之间没有固有的界限。这些只是一组编译选项。
服务器只是根据预先确定的选项进行操作。事实上,您甚至可以更改这些选项来优化您的调音。
带有跟踪声明的试用版或发行版。
2、release版本什么情况下会出现该问题?
考虑到上面的解释,我们来一一比较这些选项,看看在release版本中错误是如何发生的。
**1. 运行时库:** 链接哪些运行时函数库通常只会影响程序的性能。
性能不如release版本,因为debug版本的运行时库包含调试信息,并使用一些保护机制来帮助检测错误。编译器提供的运行时库通常非常稳定,不会出现发布版本错误。不过,调试运行时库改进了对堆内存分配等错误的检测,因此在调试中出现的错误在发布中可能是正常的。请注意,如果调试结果出错,则即使发布成功,程序也一定有错误,但发布版本的特定运行可能不会有错误。
**2.****优化:** 这是导致错误的主要原因。这是因为当优化关闭时,源程序本质上是直接翻译的,但当优化打开时,编译器会做出一系列假设。
此类错误的主要类型有:
(1)帧指针省略(简称FPO):函数调用过程中,所有调用信息(返回地址、参数)和自动变量都放在栈中。如果函数声明和实现(参数、返回值、调用方法)不同,则会出错。然而,在调试模式下,通过EBP寄存器中存储的地址来访问堆栈。如果没有出现数组越界等错误(或者越界错误不是太多),函数通常可以运行。通常情况下;
在释放模式下,优化忽略了EBP堆栈基地址指针,因此通过全局指针访问堆栈会导致返回地址错误,导致程序崩溃。 C++ 强大的类型功能可以捕获大多数此类错误,但在使用强制转换时它们不起作用。
您可以通过强制使用/Oy 编译选项来关闭发布版本中的帧指针省略来确定是否发生此错误。此类错误通常包括以下错误:
MFC 消息响应函数描述不正确。正确的是
afx_msg LRESULT OnMessageOwn(WPARAM wparam, LPARAM lparam);
ON_MESSAGE 宏包含强制转换。防止此错误的一种方法是重新定义ON_MESSAGE。
宏,将以下代码添加到stdafx.h(#include \’afxwin.h\’之后),如果函数原型不正确,则进行编译。
报告错误
#undef ON_MESSAGE
#define ON_MESSAGE(消息,memberFxn)\\
{ 消息, 0, 0, 0, AfxSig_lwl, \\
(AFX_PMSG)(AFX_PMSGW)(static_cast LRESULT (AFX_MSG_CALL \\
CWnd:)(WPARAM, LPARAM) (memberFxn) },
(2)Volatile变量:Volatile告诉编译器该变量可能被程序外部(如系统、其他进程、线程等)未知的方法修改。为了提高程序性能,优化器常常将一些变量放入寄存器中(类似于register关键字),但其他进程只能修改变量所在的内存,而寄存器中的值保持不变。如果您的程序是多线程的,或者您发现变量的值不是您所期望的但设置正确,则可能会出现此类问题。当程序在最快的优化下失败但在最少的优化下运行良好时,可能会出现此错误。尝试将volatile 添加到看起来可疑的变量中。
(3)变量优化:优化程序根据使用情况对变量进行优化。例如,在调试版本中,函数内未使用的变量可能会覆盖范围外的数组,此时该变量可能会被优化并调整到数组范围之外。边界会破坏堆栈中的有用数据。当然,真实情况比这复杂得多。与此相关的错误有:
非法访问,如超出数组范围或指针错误。例如
无效fn(无效)
{
整数我;
我=1;
整数a[4];
{
整数j;
j=1;
}
a[-1]=1;//当然错误不是那么明显。例如,下标是一个变量。
a[4]=1;
}
当数组超出范围时,j也超出范围,但该空间尚未回收,因此i和j覆盖超出范围。在Release版本中,i和j起的作用并不大,因此可能会被优化而破坏堆栈。
我们整理了上百道【运维技术栈面试题】,成为您运维面试路上的好助手。这样,你就可以安心参加面试并获得高薪offer。
这些面试题涵盖了从Shell、MySQL到K8s等云原生技术栈,适合运维行业新人以及运维行业新人的面试需求。升职或换工作以增加薪水。
本次访谈集内容为
174 运维工程师面试题128 k8s 面试题108 shell 脚本面试题200 Linux 面试题51 Docker 面试题35 Jenkis 面试题78 MongoDB 面试题17 ansible 面试题60 dubbo 面试题53 Kafka 面试题18 mysql 面试题40 nginx 面试题77 Redis 面试题Zookeeper 题28
总共1000多道面试题,内容全面且有价值。
174 道运营工程师面试问题
1.什么是运维?
2、运维人员经常需要在工作场所与操作人员进行交互。运营人员做什么工作?
3. 给定300台服务器,如何管理它们?
4.我们简单解释一下raid0、raid1和raid5这两种运行模式的运行原理和特点。
5、LVS、Nginx、HAproxy有什么区别?
6. Squid、Varinsh、Nginx 有什么区别,你在工作中如何选择?
7.Tomcat和Resin有什么区别?
8.什么是中间件?
9. Tomcat 的三个端口8005、8009、8080 是什么意思?
10.什么是CDN?
11.什么是网站灰度发布?
12、请简单说明一下DNS域名解析的过程。
13.什么是RabbitMQ?
14.Keepalived如何工作?
15.描述LVS工作流程的三种模式。
16、mysql的innodb如何识别锁定问题以及mysql如何减少主从复制延迟?
树脂和树脂有什么区别?我应该如何为我的工作选择树脂?
8.什么是中间件?
9. Tomcat 的三个端口8005、8009、8080 是什么意思?
10.什么是CDN?
11.什么是网站灰度发布?
12、请简单说明一下DNS域名解析的过程。
13.什么是RabbitMQ?
14.Keepalived如何工作?
15.描述LVS工作流程的三种模式。
16、mysql的innodb如何识别锁定问题以及mysql如何减少主从复制延迟?
17.如何重置mysql root密码?
#以上关于Debug版本和Release版本的区别_Linux Release和Debug版本的区别摘自网络,仅供参考。相关信息请参见官方公告。
原创文章,作者:CSDN,如若转载,请注明出处:https://www.sudun.com/ask/92974.html