首页 > 其他分享 >编译器优化选项和debug,release模式的区别(转)

编译器优化选项和debug,release模式的区别(转)

时间:2023-05-05 10:13:21浏览次数:37  
标签:选项 Release 模式 ftree debug 编译器 release 优化 Debug

原文:https://blog.csdn.net/qq_41854911/article/details/129657879

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

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

以上这种情况,可能很多人都遇到过。

用C/C++的朋友都知道编译器编译有各种优化级别,编译器优化级别大体如下:
O0(默认选项):不开启优化,方便功能调试

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

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

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

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

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

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

 

具体介绍如下:

O0

编译器默认就是O0,该选项下不会开启优化,方便开发者调试。O1:致力于在不需要过多的编译时间情况下,尽量减少代码大小和尽量提高程序运行速度,它开启了下面的优化标志:

-fauto-inc-dec

-fbranch-count-reg

-fcombine-stack-adjustments

-fcompare-elim

-fcprop-registers

-fdce -fdefer-pop

-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

 

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

 

O2

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

-falign-functions

-falign-jumps

-falign-labels

-falign-loops

-fcaller-saves

-fcode-hoisting

-fcrossjumping

-fcse-follow-jumps

-fcse-skip-blocks

-fdelete-null-pointer-checks

-fdevirtualize

-fdevirtualize-speculatively

-fexpensive-optimizations

-ffinite-loops

-fgcse

-fgcse-lm

-fhoist-adjacent-loads

-finline-functions

-finline-small-functions

-findirect-inlining

-fipa-bit-cp

-fipa-cp

-fipa-icf

-fipa-ra

-fipa-sra

-fipa-vrp

-fisolate-erroneous-paths-dereference

-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

 

Os

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

-falign-functions

-falign-jumps

-falign-labels

-falign-loops

-fprefetch-loop-arrays

-freorder-blocks-algorithm=stc

它还启用了-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

 

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; 
}

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字节
}

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

 

gcc常用选项总结

 

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

程序在Debug模式下运行的好好的,Release模式下就crash了,怎么办?

可以尝试着找一找代码中的assert,看一下是否是assert导致的两种模式下的差异,从这个思路入手。

程序在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

标签:选项,Release,模式,ftree,debug,编译器,release,优化,Debug
From: https://www.cnblogs.com/tan-wm/p/17373278.html

相关文章

  • 基于 CentOS Linux release 7.9.2009 的软件开发学习
    了解Linux系统:作为新手程序员,首先要熟悉Linux系统,学习基本的命令行操作,如文件和目录操作、进程管理和权限控制等。选择编程语言:根据你的兴趣和项目需求,选择一种编程语言进行学习。常用的编程语言包括Python、Java、C++、Ruby和PHP等。安装开发工具:为了进行软件开发,你需......
  • 基于centos release 7.9.2009的LINUX进行Git服务器搭建
    1.安装Git首先需要在CentOSLinux7.9.2009上安装Git。可以使用以下命令在命令行中安装:sudoyuminstallgit2.创建Git仓库在CentOS上创建Git仓库有两种方式:创建本地Git仓库或创建远程Git仓库。如果想要将CentOSLinux7.9.2009作为Git服务器,需要创建远程G......
  • 基于centos release 7.9.2009的LINUX基础知识
    以下是一些你需要了解的基本命令:ls:列出当前目录下的文件和文件夹。cd:改变当前目录。mkdir:创建新的文件夹。rm:删除文件或文件夹。vi:打开一个文本编辑器。接下来,我们将讨论一些重要的运维任务和相应的命令:安装软件包yuminstall<package-name>:使用yum命令来安装软件包......
  • c++ 调用函数,编译器查找函数过程
    假设此处调用函数 inta=1;floatb=1.0;func(a,b);//调用函数若func为非模板函数,编译器查找所有的名称为func的函数,然后检查函数入参的数量,再然后检查每个入参是否都可以转换到目标类型。(此处注意,如果参数类型为类对象,若该类支持隐式转换,那么会出现如下情况:classT......
  • PB反编译器(PBKiller) 2.5.18 特别版
    PBKiller是一款非常优秀的PB反编译器,它可以反编译PB6.7.8.9编译出来的所有对象和源码。用PBkiller软件打开相应的PBD文件,显示如下,可以只导出需要的函数、窗口等,也可以全部导出。截图:http://www.mis2erp.com/soft/PBDE03.pnghttp://www.mis2erp.com/soft/PBDE04.pnghttp://www.mis2e......
  • VC程序Release程序崩溃后问题根源查找
    Part1.如何去做崩溃后的定位是一个有效的方法。1.可以先利用连接器的配置,产生map文件:在VCProjectSetting对话框中打开Generatemapfile,然后在ProjectOptions对话框中键入“/mapinfo:lines/mapinfo:exports”,这样在./release目录下就有.pdb文件了。然后在配合这个......
  • Python MatplotlibDeprecationWarning Matplotlib 3.6 and will be removed two minor
    百度飞桨(PaddlePaddle)-数字识别在Pycharm中使用Matplotlib中的pyplot时,运行代码报错:MatplotlibDeprecationWarning:SupportforFigureCanvaseswithoutarequired_interactive_frameworkattributewasdeprecatedinMatplotlib3.6andwillberemovedtwominorreleases......
  • Debug Assertion Failed!:Expression: can't dereference out of range vector iterato
    1#include<iostream>2#include<vector>3usingnamespacestd;4boolFind(inttarget,vector<int>array){5autobegin=array.begin(),end=array.end(),mid=begin+(end-begin)/2;6while((target!=*mid)&&a......
  • 错误until the update interval of nexus-releases has elapsed or updates are force
    错误:untiltheupdateintervalofnexus-releaseshaselapsedorupdatesareforced  (从文件系统里传的,而不是从nexues界面上传的),有些文件nexues从中央仓库里下载不到,本人从别处拷贝一个上传去后,执行mvncompile时出现该错误。  解决办法:mvncleaninstall-U -Umeansfor......
  • tinyMCE编译器样式更改
    最近用这个,发现固定高度后滚动条的样式还是浏览器自带的,跟现在后台的样式不一样就有点奇怪这是更改前的样式 这是后台全局滚动的样式 差别很大,就想着优化一下,然后就去看了文档,中文文档在这里,看到了一个配置,content_css然后在项目引入tinyMCE的地方新建文件写入想要更改......