【C/C++ 编译相关 gcc】一次搞懂GCC编译选项:优化代码、调试程序必备!

简介: 【C/C++ 编译相关 gcc】一次搞懂GCC编译选项:优化代码、调试程序必备!

常见参数

 

-idir 指定头文件路径。
-llibrary 指定库library
-Ldir 定制编译的时候,搜索库的路径。
-Wl,-rpath-link=<library_dir> 定制编译的时候,搜索库的路径。
-Wl,-rpath=<library_dir> 定制运行的时候,搜索库的路径。
-o 定制目标名称,缺省的时候gcc 编译出来的文档是a.out
-O0 -O1 -O2 -O3 编译器的优化选项的4个级别,-O0表示没有优化,-O1为缺省值,-O3优化级别最高.
-shared 此选项将尽量使用动态库,所以生成文档比较小,需要提供动态库。
-static 此选项将禁止使用动态库,所以,编译出来的东西,一般都很大。
-std 指定C标准,如-std=c99使用c99标准,-std=gnu99,使用C99 再加上 GNU 的一些扩展。
-m32 程序可以同时在32位和64为机器上运行,如果使用-m64只能在64位机器.

PS: -Wl选项告诉编译器将后面的参数传递给链接器。

其他参数

-as-needed 忽略链接时没有用到的动态库
--no-as-needed  不忽略链接时没有用到的动态库
-Wl,option 把选项 option 传递给连接器,如果 option 中含有逗号,就在逗号处分割成多个选项
-c 用于把源码文件编译成 .o 对象文件,不进行链接过程
-Wall 生成常见的所有告警信息,且停止编译,具体是哪些告警信息,请参见GCC手册,一般用这个足矣!
-w 关闭所有告警信息
-fPIC 用于生成位置无关的代码
-v (在标准错误)显示执行编译阶段的命令,同时显示编译器驱动程序,预处理器,编译器的版本号

-Dmacro[=def]:定义一个宏,在编译时将macro定义为def。如果没有指定def,那么默认值为1。

-Imacro:为预处理器添加搜索目录。预处理器会在这些目录中查找#include指定的头文件。

-fno-inline:禁止编译器自动内联函数

-fno-stack-protector:关闭栈保护功能。这有助于防止缓冲区溢出攻击,但可能会略微降低性能。

-g:生成调试信息。这使得在调试器中可以更容易地调试程序。

-pg:生成gprof分析所需的性能分析信息。

-Wextra:生成额外的警告信息,可以帮助发现一些潜在的问题。

-Werror:将所有的警告信息视为错误,并停止编译。

-Wno-error:使得某个特定的警告不被当作错误处理。

-Wformat:检查printf和scanf等格式化输入/输出函数的格式字符串是否匹配实际参数。

-Wunused:检查未使用的变量、函数、参数等。

-Wuninitialized:检查未初始化的变量。

-ftime-report:输出编译期间每个步骤所花费的时间。

-ffast-math:允许编译器对数学函数进行一些不符合IEEE或ISO标准的优化,可以提高性能,但可能会导致数值不稳定。

-fopenmp:启用OpenMP并行编程支持。这允许您使用OpenMP指令来并行化程序。

GCC相关信息查看

GCC警告选项设置

列举gcc 常见和有用的编译警告选项

GCC优化等级

相关参数说明:

-fpic 用于生成位置无关代码,位置无关码的作用: 1、程序在运行期间动态加载到内存中; 2、程序在不同场合与不同程序组合后加载到内存(一般用于动态链接库) 3、在运行期间不同地址相互之间的映射;(如bootloader) 简言之,位置无关码就是可以在进程的任意内存位置执行的目标码,动态链接库必须使用。

-L.

搜索相应库文件路径,.是指当前路径;

-march=armv7-a

-march=armv7-a是指编译出来的汇编语言是针对armv7架构的;

-mtune=contex-a8

与上面一样,这个则是针对板子上的CPU选项是contex-a8类型的;

-mfloat-abi=soft/softfp/hard

"soft"选项:表明不使用FPU硬件,而是使用GCC的整数算术运算来模拟浮点运算。此选项为默认,因此一定要修改为softfp。

"softfp"选项:表明要使用FPU硬件来做浮点运算,只是,函数的参数传递到整数寄存器(r0-r3)中,然后再传递到FPU中。

"hard"选项:表明要使用FPU硬件来做浮点运算,并且,函数的参数直接传递到FPU的寄存器(s0、d0)中。

-mfpu=vfpv3-d16

指定了目标机器上可用的浮点硬件(或硬件仿真),-mfloat-abi=softfp/hard,使用硬浮点指令而不指定-mfpu的话,默认使用的是-mfpu=vfp,即不会做neon SIMD优化。因此采用neon 内置或neon 汇编,必须指定-mfpu=neon。Advanced SIMD (aka NEON) is mandatory for AArch64, so no command line option is needed to instruct the compiler to use NEON.

-mthumb-interwork

这个编译选项则是支持编译出来的汇编语言可以支持ARM和THUMB指令集;

-mno-thumb-interwork

缺省情况下是"-mno-thumb-interwork",因为指定了"-mthumb-interwork"产生的代码稍微大一些;

-Wno-write-strings

会忽略掉C++ char* 转const char*的警告,这样并不会很安全;

-Wno-trigraphs

关闭ANSI C的三字母词编译出现的错误;在ANSI C标准中,定义了9个三字母词(trigraph),三字母词就是几个字符的序列,合起来表示另一个字符。

-fno-tree-vectorize

关闭程序中的向量化的选项;gcc -O3会自动打开 -ftree-vectorize选项

-fno-inline

忽略代码中的inline关键字,该选项使编译器将内联函数以普通函数正常对待,等同于无优化选项的处理。

-fshort-enums

支持给enum类型分配它声明的值域范围的字节数,即enum类型等于大小足够的最小整数类型。

typedef enum num{

one = 1,

two = 2,

three = 3,

four = 4,

}NUM;

NUM num1;

sizeof(num1)不增加这个-fshort-enums选项的时候为4,增加后为大小为1;-fno-short-enums则是无这个选项优化处理。gcc是默认没有-fshort-enums这个选项的;

-Wundef

当一个没有定义的符号出现在 #if 中时,给出警告。

-fexpensive-optimizations

执行代价高昂的优化技术,但是不一定保证运行时性能能提升,反而可能一定程度上会产生负面影响.

-frename-registers

在寄存器分配后,通过使用rename registers来避免预定代码中的虚假依赖。

-fomit-frame-pointer

能够提高程序性能;原理上最主要的区别是少了栈帧的切换和栈地址的保存;在gdb 执行disassemble命令时,由于没有保存相应栈调用地址,而导致无法追踪函数调用顺序的问题;

-Wno-psabi

Processor Suppliment aBI (psABI)

-fno-strict-aliasing

在编译选项中加入-fstrict-aliasing的优势在于向编译器说明不同类型的lvalue将指向不相关的内存区域,编译器可以做大量的优化。而选项-fno-strict-aliasing向编译器表明不同类型的lvalue可能指向相关的内存区域,因此编译器不会做出一些极端的优化而造成不安全

-funwind-tables(为何会产生大量unwind符号?)

unwind table,这个表记录了与函数相关的信息,共三个字段:函数的起始地址,函数的结束地址,一个 info block 指针。

Similar to ‘-fexceptions’, except that it just generates any needed static data, but does not affect the generated code in any other way.

-fexceptions

Enable exception handling

注:大量unwind符号的产生部分是由于-funwind-tables以及-fexceptions,该选项会使object产生符号__aeabi_unwind_cpp_prN,在链接之后会在库文件中生成unwind符号。但是即使不定义这两个选项,如果代码中显式抛出了异常,编译器会默认添加-fexceptions,如果强制手工添加-fno-exceptions会报错。stack unwind 即从抛出异常的函数开始,沿着调用链向上找到 catch 所在的函数,然后从抛异常的地方开始,清理调用链上各栈帧内已经创建了的局部变量,这一整个过程。

-fstack-protector

在关键函数的堆栈中设置保护值。在返回地址和返回值之前,都将验证这个保护值。如果出现了缓冲区溢出,保护值不再匹配,程序就会退出。程序每次运行,保护值都是随机的,不会被远程猜出。

-finline-limit=64

对伪指令数超过n的函数,编译程序将不进行内联展开,默认为600。增大此值将增加编译时间和编译内存用量并且生成的二进制文件体积也会变大,此值不宜太大。

-fsigned-char

设定char的缺省模式为signed char

-no-canonical-prefixes

Do not expand any symbolic links, resolve references to ‘/../’ or ‘/./’, or make the path absolute when generating a relative prefx.

-fdata-sections 以及 -ffunction-sections

将每个函数或符号创建为一个sections,其中每个sections名与function或data名保持一致。即使compiler为每个function和data item分配独立的section

-Wl,–gc-sections(为何导致符号的缺失?)

指示链接器去掉不用的section(其中-wl, 表示后面的参数 -gc-sections 传递给链接器),链接操作以section作为最小的处理单元(结合-ffunction-sections),只要一个section中有某个符号被引用,该section就会被放入output中。

什么是"被引用",个人认为是指"被调用",或者符号被export引起的链接器认为这是一个接口

-Wa,--noexecstack

执行ld链接器堆栈段不可执行机制(其中-wl, 表示后面的参数 -gc-sections 传递给assembler)

-frtti

RTTI(Run-Time Type Identification),通过运行时类型信息程序能够使用基类的指针或引用来检查这些指针或引用所指的对象的实际派生类型。-frtti选项使编译器为每个有虚函数的类添加一些信息以支持rtti特性,例如 dynamic_cast typeid之类,不过这个选项默认就是打开的,一般都是用-fno-rtti来关闭这个特性节约空间

-fvisibility=hidden (LD参数)

能够实现隐藏符号表的作用,nm查看符号表可以看到符号类型从T变为t,至于如何去除局部符号t,可以调用strip -x来去掉。从动态共享库中尽可能少地输出符号是一个好的实践经验。输出一个受限制的符号会提高程序的模块性,并隐藏实现的细节。在库中减少符号的数目还可以减少库的内存印迹,减少动态链接器的工作量。动态链接器装载和识别的符号越少,程序启动和运行的速度就越快。

对于接口函数,可以在函数声明前添加__attribute__ ((visibility ("default"))),使其符号被单独导出。

目录
相关文章
|
1月前
|
自然语言处理 算法 前端开发
C++与Doxygen:精通代码文档化之道
C++与Doxygen:精通代码文档化之道
49 0
|
3天前
|
设计模式 编译器 数据安全/隐私保护
C++ 多级继承与多重继承:代码组织与灵活性的平衡
C++的多级和多重继承允许类从多个基类继承,促进代码重用和组织。优点包括代码效率和灵活性,但复杂性、菱形继承问题(导致命名冲突和歧义)以及对基类修改的脆弱性是潜在缺点。建议使用接口继承或组合来避免菱形继承。访问控制规则遵循公有、私有和受保护继承的原则。在使用这些继承形式时,需谨慎权衡优缺点。
15 1
|
4天前
|
设计模式 存储 Java
C++从入门到精通:3.5设计模式——提升代码可维护性与可扩展性的关键
C++从入门到精通:3.5设计模式——提升代码可维护性与可扩展性的关键
|
5天前
|
C++
【C++】在使用代码组装URL时,一定要注意的坑......
【C++】在使用代码组装URL时,一定要注意的坑......
10 0
|
26天前
|
C语言 C++ 容器
C调用C++代码
C调用C++代码
12 1
|
27天前
|
存储 缓存 C++
C++链表常用的函数编写(增查删改)内附完整程序
C++链表常用的函数编写(增查删改)内附完整程序
|
6天前
|
存储 编译器 C语言
c++的学习之路:5、类和对象(1)
c++的学习之路:5、类和对象(1)
22 0
|
6天前
|
C++
c++的学习之路:7、类和对象(3)
c++的学习之路:7、类和对象(3)
19 0
|
5天前
|
设计模式 Java C++
【C++高阶(八)】单例模式&特殊类的设计
【C++高阶(八)】单例模式&特殊类的设计
|
5天前
|
编译器 C++
【C++基础(八)】类和对象(下)--初始化列表,友元,匿名对象
【C++基础(八)】类和对象(下)--初始化列表,友元,匿名对象