Debug和Release

Debug模式和Release模式有什么区别?有时候程序在Debug模式下运行的好好的,Release模式下就crash了,又有些时候程序在Debug模式下会崩溃,Release模式下却正常运行,这都是怎么回事?
C/C++编译器有各种优化级别,编译器优化级别大体如下:
●O0(默认):不开启优化,方便功能调试(Debug模式)
●Og:方便调试的优化(比O1更保守)
●O1:保守的优化,打开了四十多个优化选项
●O2:常用的发布优化,在O1的基础上额外打开了四十多个优化选项,包括自动内联等规则(Release模式)
●Os:产生较小代码体积的优化(比O2更保守)
●O3:较为激进的优化(对错误编码容忍度最低),在O2的基础上额外打开了十多个优化选项
●Ofast:打开可导致不符合IEEE浮点数等标准的性能优化选项。
上述优化级别如果想要了解具体含义可以看官方文档:https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
编译器有这么多优化级别,Debug版本和Release版本其实就是优化级别的区别,Debug称为调试版本,编译的结果通常包含有调试信息,没有做任何优化,方便开发人员进行调试,Release称为发布版本,不会携带调试信息,同时编译器对代码进行了很多优化,使代码更小,速度更快,发布给用户使用,给用户使用以更好的体验,特殊情况下,可以看到两种模式在运行速度上有数量级的差距。但Release模式编译比Debug模式花的时间也会更多。Debug模式下在内存分配上有所区别,在我们申请内存时,Debug模式会多申请一部分空间,分布在内存块的前后,用于存放调试信息。对于未初始化的变量,Debug模式下会默认对其进行初始化,而Release模式则不会,所以就有个常见的问题,局部变量未初始化时,Debug模式和Release模式表现有所不同。

bool func() {
    bool found;
    for (int i = 0; i < vec.size(); ++i) {
        if (vec[i] == 3) {
            found = true;
        }
    }
    return found; 
}

Debug模式下可能运行正常,但Release模式下可能会返回错误结果,因为found局部变量在Release模式下没有初始化。
Debug模式以32字节为单位分配内存,例如当申请24字节内存时,Release模式下是正常的分配24字节,Debug模式会分配32字节,多了8字节,所以有些数组越界问题在Debug模式下可以安全运行,Release模式下就会出问题。
数据溢出问题,在一个函数中,存在某些从未被使用的变量,且函数内存在数据溢出问题,在Debug模式下可能不会产生问题,因为不会对该变量进行优化,它在栈空间中还是占有几个字节,但是Release模式下可能会出问题,Release模式下可能会优化掉此变量,栈空间相应变小,数据溢出就会导致栈内存损坏,有可能会产生奇奇怪怪的错误。例如:

void func() {
    char buffer[10];
    int counter;
    lstrcpy(buffer, "abcdefghijk"); // 需要拷贝11字节
}

下面是Debug模式崩溃,Rlease模式正常的几种情况:
●Debug模式下可以使用assert,运行过程中有异常现象会及时crash,Release模式下模式下不会编译assert,遇到不期望的情况不会及时crash,稀里糊涂继续运行,到后期可能会产生奇奇怪怪的错误,不易调试,殊不知其实在很早之前就出现了问题。编译器在Debug模式下定义_DEBUG宏,Release模式下定义NDEBUG宏,预处理器就是根据对应宏来判断是否开启assert的。
●Debug模式有运行时检查,检测堆栈溢出。Relase模式没有,程序可以继续运行,但溢出可能导致程序在其他未知的情况下出错或崩溃。所以这时应该让代码在Debug环境下跑一遍,找到溢出位置。例如:

    QObject * objects[2];

    objects[0] = new QObject;
    objects[1] = new QObject;
    objects[2] = new QObject;

最后,不要将Debug库和Release库混合在一起,可能会出问题,至于为啥会出问题,我也不知道,一般都是有两个目录,Debug目录和Release目录。我们要尽量在Debug模式下开发,先规避掉一些问题,然后再切换到Release模式下编译发布。
总之,无论在哪种模式下崩溃,一般还是代码有点问题。这样那些“未定义”的行为很多他都假定你是规范的,然后被他用来做各种优化。说白了就是游走在灰色地带违规边缘的一些操作,原来潜规则是认的(留有余地),现在严了不认了(要合并语句、内联等做优化),编译器的行为会大不一样。避免这类问题最简单的方法就是把代码写规范。

附录:
未定义的行为(Undefined Behavior)列表

原文链接:Debug和Release-CSDN博客 

  • 8
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

草上爬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值