Debug模式和Release模式有什么区别你知道吗?

开发 前端
爱玲曾说过:“开发过程就是个玄学。”有时候,程序在Debug模式下运行的好好的,一Release就crash了。

 [[381126]]

本文转载自微信公众号「程序喵大人」,作者程序喵大人 。转载本文请联系程序喵大人公众号。

张爱玲曾说过:“开发过程就是个玄学。”

有时候,程序在Debug模式下运行的好好的,一Release就crash了。

有时候,程序在Debug模式下崩溃了,Release模式下居然能正常运行。

可能很多人都遇到过以上的情况。

 

用C/C++的朋友都知道编译器编译有各种优化级别,编译器优化级别大体如下:

O0(默认选项):不开启优化,方便功能调试

Og:方便调试的优化选项(比O1更保守)

O1:保守的优化选项,打开了四十多个优化选项

O2:常用的发布优化选项,在O1的基础上额外打开了四十多个优化选项,包括自动内联等规则

Os:产生较小代码体积的优化选项(比O2更保守)

O3:较为激进的优化选项(对错误编码容忍度最低),在O2的基础上额外打开了十多个优化选项

Ofast:打开可导致不符合IEEE浮点数等标准的性能优化选项。

具体介绍如下:

O0:编译器默认就是O0,该选项下不会开启优化,方便开发者调试。

O1:致力于在不需要过多的编译时间情况下,尽量减少代码大小和尽量提高程序运行速度,它开启了下面的优化标志:

-fdelayed-branch 
 
-fdse 
 
-fforward-propagate  
 
-fguess-branch-probability  
 
-fif-conversion 
 
-fif-conversion2 
 
-finline-functions-called-once 
 
-fipa-modref 
 
-fipa-profile 
 
-fipa-pure-const 
 
-fipa-reference 
 
-fipa-reference-addressable 
 
-fmerge-constants 
 
-fmove-loop-invariants 
 
-fomit-frame-pointer 
 
-freorder-blocks 
 
-fshrink-wrap 
 
-fshrink-wrap-separate 
 
-fsplit-wide-types 
 
-fssa-backprop 
 
-fssa-phiopt  
 
-ftree-bit-ccp 
 
-ftree-ccp 
 
-ftree-ch 
 
-ftree-coalesce-vars 
 
-ftree-copy-prop 
 
-ftree-dce 
 
ftree-dominator-opts 
 
-ftree-dse 
 
-ftree-forwprop  
 
-ftree-fre 
 
-ftree-phiprop 
 
-ftree-pta 
 
-ftree-scev-cprop 
 
-ftree-sink  
 
-ftree-slsr 
 
-ftree-sra  
 
-ftree-ter 
 
-funit-at-a-time 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.

Og:如果是为了调试,该选项是比O0更好的选择,它会打开O1大部分优化标志,但是不会启用那些影响调试的标志:

-fbranch-count-reg                                         
 
-fdelayed-branch 
 
-fdse 
 
-fif-conversion 
 
-fif-conversion2 
 
-finline-functions-called-once 
 
-fmove-loop-invariants 
 
-fssa-phiopt 
 
-ftree-bit-ccp  
 
-ftree-dse 
 
-ftree-pta  
 
-ftree-sra 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.

O2:常见的Release级别,该选项下几乎执行了所有支持的优化选项,它增加了编译时间,提高了程序的运行速度,又额外打开了以下优化标志:

-flra-remat 
 
 -foptimize-sibling-calls 
 
 -foptimize-strlen 
 
 -fpartial-inlining 
 
 -fpeephole2 
 
 -freorder-blocks-algorithm=stc 
 
 -freorder-blocks-and-partition 
 
  -freorder-functions 
 
 -frerun-cse-after-loop 
 
   -fschedule-insns 
 
  -fschedule-insns2 -fsched-interblock 
 
  -fsched-spec 
 
 -fstore-merging 
 
 -fstrict-aliasing 
 
 -fthread-jumps 
 
 -ftree-builtin-call-dce 
 
 -ftree-pre 
 
 -ftree-switch-conversion 
 
  -ftree-tail-merge 
 
 -ftree-vrp 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.

Os:打开了几乎所有的O2优化标志,除了那些经常会增加代码大小的优化标志:

-falign-functions                                                 
 
-falign-jumps 
 
-falign-labels 
 
-falign-loops 
 
-fprefetch-loop-arrays 
 
-freorder-blocks-algorithm=stc 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

它还启用了-finline-functions优化标志,使编译器根据代码大小而不是程序运行速度进行优化,为了减少代码大小。

O3:在O2的基础上又打开了以下优化标志

-fgcse-after-reload                                          
 
-fipa-cp-clone 
 
-floop-interchange 
 
-floop-unroll-and-jam 
 
-fpeel-loops 
 
-fpredictive-commoning 
 
-fsplit-loops 
 
-fsplit-paths 
 
-ftree-loop-distribution 
 
-ftree-loop-vectorize 
 
-ftree-partial-pre 
 
-ftree-slp-vectorize 
 
-funswitch-loops 
 
-fvect-cost-model 
 
-fvect-cost-model=dynamic 
 
-fversion-loops-for-strides 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.

Ofast:更加激进的编译选项,它不会严格遵循标准,在O3的优化基础上,它又开启了一些可能导致不符合IEEE浮点数等标准的性能优化选项,如- fast-math, -fallow-store-data-races等。

tips:上述优化选项如果想要了解具体含义可以看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;  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

Debug模式下可能运行正常,但Release模式下可能会返回错误结果,因为found局部变量在Release模式下没有初始化。

Debug模式以32字节为单位分配内存,例如当申请24字节内存时,Release模式下是正常的分配24字节,Debug模式会分配32字节,多了8字节,所以有些数组越界问题在Debug模式下可以安全运行,Release模式下就会出问题。

Debug模式下可以使用assert,运行过程中有异常现象会及时crash,Release模式下模式下不会编译assert,遇到不期望的情况不会及时crash,稀里糊涂继续运行,到后期可能会产生奇奇怪怪的错误,不易调试,殊不知其实在很早之前就出现了问题。编译器在Debug模式下定义_DEBUG宏,Release模式下定义NDEBUG宏,预处理器就是根据对应宏来判断是否开启assert的。

数据溢出问题,在一个函数中,存在某些从未被使用的变量,且函数内存在数据溢出问题,在Debug模式下可能不会产生问题,因为不会对该变量进行优化,它在栈空间中还是占有几个字节,但是Release模式下可能会出问题,Release模式下可能会优化掉此变量,栈空间相应变小,数据溢出就会导致栈内存损坏,有可能会产生奇奇怪怪的错误。

例如:

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

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

tips:不要将Debug库和Release库混合在一起,可能会出问题,至于为啥会出问题,知道的可在下方评论区留言,一般都是有两个目录,Debug目录和Release目录。

回到开篇提到的那两个问题:

 

参考资料

http://www.flounder.com/debug_release.htm

https://vinayakgarg.wordpress.com/2012/03/31/difference-between-debug-build-and-release-build/

https://www.xspdf.com/resolution/312312.html

https://docs.oracle.com/cd/E19205-01/820-1214/bkacs/index.html

https://www.cnblogs.com/huaping-audio/archive/2008/08/23/1274833.html

https://www.zhihu.com/question/27090458

https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html

 

责任编辑:武晓燕 来源: 程序喵大人
相关推荐

2024-05-27 00:00:00

localhostIPv6IPv4

2022-03-13 18:53:31

interfacetypeTypeScript

2022-06-08 07:34:25

InnoDBdeleteMySQL

2021-07-27 08:02:45

DTO 软件Pojo

2022-08-26 01:41:42

GPUCPU架构

2018-10-26 10:41:06

ApacheNginx服务器

2022-07-05 08:05:00

策略模式接口实现类

2024-11-26 14:29:48

2024-10-22 09:59:36

虚拟化容器化系统

2016-12-19 09:21:26

WindowsClean Boot区别

2022-02-18 17:21:29

适配器模式客户端

2024-03-26 00:10:08

预测AI泛化

2022-05-16 11:04:43

RocketMQPUSH 模式PULL 模式

2024-01-01 08:25:53

ViewSurface框架

2019-12-02 10:16:46

架构设计模式

2024-07-03 08:33:08

2018-07-04 11:02:23

无线传输模式

2023-06-01 08:15:04

CentOS红帽

2023-12-07 07:08:09

Angular函数

2019-02-12 11:15:15

Spring设计模式Java
点赞
收藏

51CTO技术栈公众号