gcc3

  • Post author:
  • Post category:其他



GCC 3


Section: GNU Tools (1)

Updated: 2003/12/05



调试选项


(DEBUGGING OPTION)


GNU CC


拥有许多特别选项


,


既可以调试用户的程序


,


也可以对


GCC


排错


:



-g


以操作系统的本地格式


(stabs, COFF, XCOFF,





DWARF).


产生调试信息


. GDB


能够使用这些调试信息


.


在大多数使用


stabs


格式的系统上


, `

-g




选项启动只有


GDB


才使用的额外调试信息


;


这些信息使


GDB


调试效果更好


,


但是有可能导致其他调试器崩溃


,


或拒绝读入程序


.


如果你确定要控制是否生成额外的信息


,


使用


`

-gstabs+

‘, `

-gstabs

‘, `

-gxcoff+

‘, `

-gxcoff

‘, `

-gdwarf+

‘,





`

-gdwarf

‘ (


见下文


).


和大多数


C


编译器不同


, GNU CC


允许结合使用


`

-g







`

-O




选项


.


优化的代码偶尔制造 一些惊异的结果


:


某些声明过的变量根本不存在


;


控制流程直接跑到没有预料到的地方


;


某些语句因为计算结果是常量或已经确定而 没有执行


;


某些语句在其他地方执行


,


因为他们被移到循环外面了


.


然而它证明了调试优化的输出是可能的


.


对可能含有错误的程序使用优化器是合理的


.


如果


GNU CC


支持输出多种调试信息


,


下面的选项则非常有用


.



-ggdb


以本地格式


(


如果支持


)


输出调试信息


,


尽可能包括


GDB


扩展


.



-gstabs





stabs


格式


(


如果支持


)


输出调试信息


,


不包括


GDB


扩展


.


这是大多数


BSD


系统上


DBX


使用的格式


.



-gstabs+





stabs


格式


(


如果支持


)


输出调试信息


,


使用只有


GNU


调试器


(GDB)


理解的


GNU


扩展


.


使用这些扩展有可能导致 其他调试器崩溃或拒绝读入程序


.



-gcoff





COFF


格式


(


如果支持


)


输出调试信息


.


这是在


System V


第四版以前的大多数


System V


系统上


SDB


使用的 格式


.



-gxcoff





XCOFF


格式


(


如果支持


)


输出调试信息


.


这是


IBM RS/6000


系统上


DBX


调试器使用的格式


.



-gxcoff+





XCOFF


格式


(


如果支持


)


输出调试信息


,


使用只有


GNU


调试器


(GDB)


理解的


GNU


扩展


.


使用这些扩展有可能导致 其他调试器崩溃或拒绝读入程序


.



-gdwarf





DWARF


格式


(


如果支持


)


输出调试信息


.


这是大多数


System V


第四版系统上


SDB


使用的格式


.



-gdwarf+





DWARF


格式


(


如果支持


)


输出调试信息


,


使用只有


GNU


调试器


(GDB)


理解的


GNU


扩展


.


使用这些扩展有可能导致 其他调试器崩溃或拒绝读入程序


.



-g


level



-ggdb


level



-gstabs


level



-gcoff


level


-gxcoff


level



-gdwarf


level


请求生成调试信息


,


同时用



level



指出需要多少信息


.


默认的


level


值是


2.


Level 1


输出最少量的信息


,


仅够在不打算调试的程序段内


backtrace.


包括函数和外部变量的描述


,


但是 没有局部变量和行号信息


.


Level 3


包含更多的信息


,


如程序中出现的所有宏定义


.


当使用


`

-g3




选项的时候


,


某些调试器支持 宏扩展


.



-p


产生额外代码


,


用于输出


profile


信息


,


供分析程序



prof



使用


.



-pg


产生额外代码


,


用于输出


profile


信息


,


供分析程序



gprof



使用


.



-a


产生额外代码


,


用于输出基本块


(basic block)





profile


信息


,


它记录各个基本块的执行次数


,


供诸如



tcov



此类的程序分析


.


但是注意


,


这个数据格式并非



tcov



期待的


.


最终


GNU

gprof



将处理这些数据


.



-ax


产生额外代码


,


用于从


‘bb.in’


文件读取基本块的


profile


参数


,





profile


的结果写到


‘bb.out’


文件


. `bb.in’


包含一张函数列表


.


一旦进入列表中的某个函数


, profile


操作就开始


,


离开最外层的函数后


, profile


操作就结束


.





`-‘


为前缀名的函数排除在


profile


操作之外


.


如果函数名不是唯一的


,


它可以写成


`/path/filename.d:functionname’


来澄清


. `bb.out’


将列出一些有效的文件名


.


这四个函数名具有 特殊含义


: `__bb_jumps__’


导致跳转


(jump)


频率写进


`bb.out’. `__bb_trace__’


导致基本块序列通过 管道传到


`gzip’,


输出


`bbtrace.gz’


文件


. `__bb_hidecall__’


导致从跟踪


(trace)


中排除


call


指令


. `__bb_showret__’


导致在跟踪中包括返回指令


.



-d


letters


编译的时候


,






letters



指定的时刻做调试转储


(dump).


用于调试编译器


.


大多数转储的文件名 通过源文件名添加字词获得


(


例如


`

foo.c.rtl







`

foo.c.jump

‘).



-dM


预处理结束的时候转储所有的宏定义


,


不输出到文件


.



-dN


预处理结束的时候转储所有的宏名


.



-dD


预处理结束的时候转储所有的宏定义


,


同时进行正常输出


.



-dy


语法分析


(parse)


的时候在标准错误转储调试信息


.



-dr


RTL


阶段后转储到


`

file


.rtl

‘.



-dx


仅对函数生成


RTL,


而不是编译


.


通常和


`

r




联用


.



-dj


第一次跳转优化后转储到


`

file


.jump

‘.



-ds


CSE (


包括有时候跟在


CSE


后面的跳转优化


)


后转储到


`

file


.cse

‘.



-dL


循环优化后转储到


`

file


.loop

‘.



-dt


第二次


CSE


处理


(


包括有时候跟在


CSE


后面的跳转优化


)


后转储到


`

file


.cse2

‘.



-df


流程分析


(flow analysis)


后转储到


`

file


.flow

‘.



-dc


指令组合


(instruction combination)


后转储到


`

file


.combine

‘.



-dS


第一次指令安排


(instruction schedule)


后转储到


`

file


.sched

‘.



-dl


局部寄存器分配后转储到


`

file


.lreg

‘.



-dg


全局寄存器分配后转储到


`

file


.greg

‘.



-dR


第二次指令安排


(instruction schedule)


后转储到


`

file


.sched2

‘.



-dJ


最后一次跳转优化后转储到


`

file


.jump2

‘.



-dd


推迟分支调度


(delayed branch scheduling)


后转储到


`

file


.dbr

‘.



-dk


寄存器





堆栈转换后转储到


`

file


.stack

‘.



-da


产生以上所有的转储


.



-dm


运行结束后


,


在标准错误显示内存使用统计


.



-dp


在汇编输出加注指明使用了哪些模式


(pattern)


及其替代模式


.



-fpretend-float


交叉编译的时候


,


假定目标机和宿主机使用同样的浮点格式


.


它导致输出错误的浮点常数


,


但是在目标机上运行的时候


,


真实的指令序列有可能和


GNU CC


希望的一样


.



-save-temps


保存那些通常是





临时





的中间文件


;


置于当前目录下


,


并且根据源文件命名


.


因此


,





`

-c -save-temps




选项编译


`

foo.c




会生成


`

foo.cpp







`

foo.s




以及


`

foo.o




文件


.



-print-file-name=


library


显示库文件



library



的全路径名


,


连接时会使用这个库





其他什么事情都不作


.


根据这个选项


, GNU CC


既不编译


,


也不连接


,


仅仅显示文件名


.



-print-libgcc-file-name





`

-print-file-name=libgcc.a




一样


.



-print-prog-name=


program


类似于


`

-print-file-name

‘,


但是查找程序


program





`

cpp

‘.


优化选项


(OPTIMIZATION OPTION)


这些选项控制多种优化措施


:



-O



-O1


优化


.


对于大函数


,


优化编译占用稍微多的时间和相当大的内存


.


不使用


`

-O




选项时


,


编译器的目标是减少编译的开销


,


使编译结果能够调试


.


语句是独立的


:


如果在 两条语句之间用断点中止程序


,


你可以对任何变量重新赋值


,


或者在函数体内把程序计数器指到其他语句


,


以及从源程序中 精确地获取你期待的结果


.


不使用


`

-O




选项时


,


只有声明了



register



的变量才分配使用寄存器


.


编译结果比不用


`

-O




选项的


PCC


要略逊一筹


.


使用了


`

-O




选项


,


编译器会试图减少目标码的大小和执行时间


.


如果指定了


`

-O




选项


, `

-fthread-jumps







`

-fdefer-pop




选项将被 打开


.


在有


delay slot


的机器上


, `

-fdelayed-branch




选项将被打开


.


在即使没有帧指针


(frame pointer)


也支持调试的机器上


, `

-fomit-frame-pointer




选项将被打开


.


某些机器上 还可能会打开其他选项


.



-O2


多优化一些


.


除了涉及空间和速度交换的优化选项


,


执行几乎所有的优化工作


.


例如不进行循环展开


(loop unrolling)


和函数内嵌


(inlining).






-O



选项比较


,


这个选项既增加了编译时间


,


也提高了生成代码的 运行效果


.



-O3


优化的更多


.


除了打开



-O2



所做的一切


,


它还打开了



-finline-functions



选项


.



-O0


不优化


.


如果指定了多个



-O



选项


,


不管带不带数字


,


最后一个选项才是生效的选项


.


诸如


`

-f


flag




此类的选项描述一些机器无关的开关


.


大多数开关具有肯定和否定两种格式


; `

-ffoo




开关选项的否定格式应该是


`

-fno-foo

‘.


下面的列表只展示了一种格式





那个不是 默认选项的格式


.


你可以通过去掉或添加


`

no-




构造出另一种格式


.



-ffloat-store


不要在寄存器中存放浮点变量


.


这样可以防止某些机器上不希望的过高精度


,





68000


的浮点寄存器


(


来自


68881)


保存的精度超过了



double



应该具有的精度


.


对于大多数程序


,


过高精度只有好处


.


但是有些程序严格依赖于


IEEE


浮点数的定义


.


对这样的程序可以使用


`

-ffloat-store




选项


.



-fmemoize-lookups



-fsave-memoized


使用探索法


(heuristic)


进行更快的编译


(


仅对


C++).


默认情况下不使用探索法


.


由于探索法只对某些输入文件 有效


,


其他程序的编译速度会变得更慢


.


第一次编译器必须对成员函数


(


或对成员数据的引用


)


建立一个调用


.


它必须


(1)


判断出这个类是否实现了那个名字的 成员函数


; (2)


决定调用哪个成员函数


(


涉及到推测需要做哪种类型转换


); (3)


检查成员函数对调用者是否可见


.


所有这些构成 更慢的编译


.


一般情形


,


第二次对成员函数


(


或对成员数据的引用


)


建立的调用


,


必须再次经过相同长度的处理


.


这意味着象 这样的代码


cout << “This ” << p << ” has ” << n << ” legs./n”;


对整个三步骤要做六次遍历


.


通过使用软件缓存


, “


命中





能够显著地减少这种代价


.


然而不幸的是


,


使用这种缓存 必须实现其他机制


,


带来了它自己的开销


. `

-fmemoize-lookups




选项打开软件缓存


.


因为函数的正文环境不同


,


函数对成员和成员函数的访问权


(


可见性


)


也可能不同


,

g++



可能需要刷新缓存


.


使用


`

-fmemoize-lookups




选项


,


每编译完一个函数就刷新缓存


.





`-fsave-memoized’


选项 也启用同样的缓存


,


但是当编译器发觉最后编译的函数的正文环境产生的访问权和下一个待编译的函数相同


,


编译器就 保留缓存内容


.


这对某个类定义许多成员函数时非常有用


:


除了某些其他类的友函数


,


每个成员函数拥有和其他成员函数完全一样 的访问权


,


因而无需刷新缓存


.



-fno-default-inline


默认为不要把成员函数内嵌


,


因为它们定义在类的作用域内


(





C++).



-fno-defer-pop


一旦函数返回


,


参数就立即弹出


.


对于那些调用函数后必须弹出参数的机器


,


编译器一般情况下让几次函数调用的参数 堆积在栈上


,


然后一次全部弹出


.



-fforce-mem


做数学运算前把将要使用的内存操作数送入寄存器


.


通过把内存访问转换成潜在的公共子表达式


,


它可能产生较好的目标码


.


如果它们不是公共子表达式


,


指令组合应该消除各自的寄存器载荷


.


我乐意倾听不同意见


.



-fforce-addr


做数学运算前把将要使用的内存地址常数送入寄存器


.


它可能和


`

-fforce-mem




一样产生较好的 目标码


.


我乐意倾听不同意见


.



-fomit-frame-pointer


对于不需要帧指针


(frame pointer)


的函数


,


不要在寄存器中保存帧指针


.


这样能够避免保存


,


设置和恢复 帧指针的指令


;


同时对许多函数提供一个额外的寄存器


.



但是在大多数机器上将无法调试



.


某些机器上


,





Vax,


这个选项无效


,


因为标准调用序列自动处理帧指针


,


通过假装不存在而不保存任何东西


.


机器描述宏



FRAME_POINTER_REQUIRED



控制目标机是否支持这个选项


.



-finline-functions


把所有简单的函数集成进调用者


.


编译器探索式地决定哪些函数足够简单


,


值得这种集成


.


如果集成了所有给定函数的调用


,


而且函数声明为



static

,


那么一般说来


GCC


有权不按汇编代码输出函数


.



-fcaller-saves


允许在寄存器里分配数值


,


但是这个方案通常受到各个函数调用的冲击


,


因此


GCC


生成额外的代码


,


在函数调用的 前后保存和复原寄存器内容


.


仅当生成代码看上去优于反之结果时才实现这样的分配


.


某些机器上该选项默认为允许


,


通常这些机器没有调用保护寄存器代替使用


.



-fkeep-inline-functions


即使集成了某个函数的所有调用


,


而且该函数声明为



static

,


仍然输出这个函数一个独立的


,


运行时可调用 的版本


.



-fno-function-cse


不要把函数地址存入寄存器


;


让调用固定函数的指令显式给出函数地址


.


这个选项产生效率较低的目标码


,


但是如果不用这个选项


,


某些不寻常的


hack,


改变汇编器的输出


,


可能因优化而带来 困惑


.



-fno-peephole


禁止任何机器相关的


peephole


优化


.



-ffast-math


这个选项出于速度优化


,


允许


GCC


违反某些


ANSI





IEEE


规则


/


规格


.


例如


,


它允许编译器假设



sqrt



函数的参数是非负数


.


这个选项不被任何


`

-O




选项打开


,


因为对于严格依靠


IEEE





ANSI


规则


/


规格实现的数学函数


,


程序可能 会产生错误的结果


.


下列选项控制特定的优化


. `

-O2




选项打开下面的大多数优化项


,


除了


`

-funroll-loops







`

-funroll-all-loops







.





`

-O




选项通常打开


`

-fthread-jumps







`

-fdelayed-branch




优化项


,


但是特定的机器上的默认优化项有可能改变


.


如果特别情况下非常需要





微调





优化


,


你可以使用下面的选项


.



-fstrength-reduce


执行循环强度缩小


(loop strength reduction)


优化


,


并且消除重复变量


.



-fthread-jumps


执行优化的地点是


,


如果某个跳转分支的目的地存在另一个条件比较


,


而且该条件比较包含在前一个比较语句之内


,


那么 执行优化


.


根据条件是


true


或者


false,


前面那条分支重定向到第二条分支的目的地或者紧跟在第二条分支后面


.



-funroll-loops


执行循环展开


(loop unrolling)


优化


.


仅对循环次数能够在编译时或运行时确定的循环实行


.



-funroll-all-loops


执行循环展开


(loop unrolling)


优化


.


对所有循环实行


.


通常使程序运行的更慢


.



-fcse-follow-jumps


在公共子表达式消元


(common subexpression elimination)


的时候


,


如果没有其他路径到达某个跳转的 目的地


,


就扫过这条


jump


指令


.


例如


,


如果


CSE


遇到带有



else



从句的



if



语句


,


当条件测试为


false





, CSE


就跟在


jump


后面


.



-fcse-skip-blocks


它类似于


`

-fcse-follow-jumps




选项


,


但是


CSE


跟在条件跳转后面


,


条件跳转跳过了 语句块


(block).


如果


CSE


遇到一条简单的



if



语句


,


不带


else


从句


, `

-fcse-skip-blocks




选项将导致


CSE


跟在



if



产生的跳转后面


.



-frerun-cse-after-loop


执行循环优化后


,


重新进行公共子表达式消元


.



-felide-constructors


如果看上去合理就省略构造子


(





C++).


根据这个选项


,


对于下面的代码


, GNU C++


直接从调用



foo



初始化



y

,


而无需通过临时变量


:


A foo (); A y = foo ();


如果没有这个选项


, GNU C++


首先通过调用类型



A



合适的构造子初始化



y

;


然后把



foo



的结果赋给临时变量


;


最后


,


用临时变量替换


`

y




的初始值


.


ANSI C++


标准草案规定了默认行为


(`

-fno-elide-constructors

‘).


如果程序的构造子存在 副效应


, `

-felide-constructors




选项能够使程序有不同的表现


,


因为可能忽略一些构造子的调用


.



-fexpensive-optimizations


执行一些相对开销较大的次要优化


.



-fdelayed-branch


如果对目标机支持这个功能


,


它试图重新排列指令


,


以便利用延迟分支


(delayed branch)


指令后面的指令空隙


.



-fschedule-insns


如果对目标机支持这个功能


,


它试图重新排列指令


,


以便消除因数据未绪造成的执行停顿


.


这可以帮助浮点运算或内存访问 较慢的机器调取指令


,


允许其他指令先执行


,


直到调取指令或浮点运算完成


.



-fschedule-insns2


类似于


`

-fschedule-insns




选项


,


但是在寄存器分配完成后


,


需要一个额外的指令调度过程


.


对于 寄存器数目相对较少


,


而且取内存指令大于一个周期的机器


,


这个选项特别有用


.


目标机选项


(TARGET OPTION)


缺省情况下


, GNU CC


编译出本机类型的目标码


.


然而也可以把他安装成交叉编译器


,


为其他机型编译程序


.


事实上


,


针对不同的目标机


,


可以同时安装


GNU CC


相应的配置


.


然后用


`

-b




选项指定 目标机种


.


顺便提一下


,


新版本和旧版本的


GNU CC


可以共存


.


其中一个版本


(


可能是最新的那个


)


为缺省版本


,


但是有时候你希望使用 其他版本


.



-b


machine


参数



machine



指出编译的目标机种


.


这个选项用于安装为交叉编译器的


GNU CC.


参数



machine



的值和配置


GNU CC


交叉编译器时设置的机器类型一样


.


例如


,


如果交叉编译器配置有


`

configure

i386v’,


意思是编译


80386


上的


System V


目标码


,


那么你可以通过


`

-b i386v




运行交叉编译器


.


如果没有指定


`

-b




选项


,


通常指编译本机目标码


.



-V


version


参数



version



指出运行哪个版本的


GNU CC.


这个选项用于安装了多个版本的


GCC.


例如


,


如果



version






`

2.0

‘,


意味着运行


GNU CC 2.0





.


如果没有指定


`

-V




选项


,


缺省版本取决于


GNU CC


的安装方式


,


一般说来推荐使用通用版本


.