【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"))),使其符号被单独导出。

目录
相关文章
|
27天前
|
C++
C++ 语言异常处理实战:在编程潮流中坚守稳定,开启代码可靠之旅
【8月更文挑战第22天】C++的异常处理机制是确保程序稳定的关键特性。它允许程序在遇到错误时优雅地响应而非直接崩溃。通过`throw`抛出异常,并用`catch`捕获处理,可使程序控制流跳转至错误处理代码。例如,在进行除法运算或文件读取时,若发生除数为零或文件无法打开等错误,则可通过抛出异常并在调用处捕获来妥善处理这些情况。恰当使用异常处理能显著提升程序的健壮性和维护性。
42 2
|
20天前
|
算法框架/工具 C++ Python
根据相机旋转矩阵求解三个轴的旋转角/欧拉角/姿态角 或 旋转矩阵与欧拉角(Euler Angles)之间的相互转换,以及python和C++代码实现
根据相机旋转矩阵求解三个轴的旋转角/欧拉角/姿态角 或 旋转矩阵与欧拉角(Euler Angles)之间的相互转换,以及python和C++代码实现
89 0
|
2月前
|
消息中间件 Java C语言
消息队列 MQ使用问题之在使用C++客户端和GBase的ESQL进行编译时出现core dump,该怎么办
消息队列(MQ)是一种用于异步通信和解耦的应用程序间消息传递的服务,广泛应用于分布式系统中。针对不同的MQ产品,如阿里云的RocketMQ、RabbitMQ等,它们在实现上述场景时可能会有不同的特性和优势,比如RocketMQ强调高吞吐量、低延迟和高可用性,适合大规模分布式系统;而RabbitMQ则以其灵活的路由规则和丰富的协议支持受到青睐。下面是一些常见的消息队列MQ产品的使用场景合集,这些场景涵盖了多种行业和业务需求。
|
8天前
|
Ubuntu Linux Shell
C++ 之 perf+火焰图分析与调试
简介 在遇到一些内存异常的时候,经常这部分的代码是很难去进行分析的,最近了解到Perf这个神器,这里也展开介绍一下如何使用Perf以及如何去画火焰图。 1. Perf 基础 1.1 Perf 简介 perf是Linux下的一款性能分析工具,能够进行函数级与指令级的热点查找。利用perf剖析程序性能时,需要指定当前测试的性能时间。性能事件是指在处理器或操作系统中发生的,可能影响到程序性能的硬件事件或软件事件 1.2 Perf的安装 ubuntu 18.04: sudo apt install linux-tools-common linux-tools-4.15.0-106-gen
13 2
|
27天前
|
程序员 C++ 开发者
C++命名空间揭秘:一招解决全局冲突,让你的代码模块化战斗值飙升!
【8月更文挑战第22天】在C++中,命名空间是解决命名冲突的关键机制,它帮助开发者组织代码并提升可维护性。本文通过一个图形库开发案例,展示了如何利用命名空间避免圆形和矩形类间的命名冲突。通过定义和实现这些类,并在主函数中使用命名空间创建对象及调用方法,我们不仅解决了冲突问题,还提高了代码的模块化程度和组织结构。这为实际项目开发提供了宝贵的参考经验。
42 2
|
27天前
|
C++
拥抱C++面向对象编程,解锁软件开发新境界!从混乱到有序,你的代码也能成为高效能战士!
【8月更文挑战第22天】C++凭借其强大的面向对象编程(OOP)能力,在构建复杂软件系统时不可或缺。OOP通过封装数据和操作这些数据的方法于对象中,提升了代码的模块化、重用性和可扩展性。非OOP方式(过程化编程)下,数据与处理逻辑分离,导致维护困难。而OOP将学生信息及其操作整合到`Student`类中,增强代码的可读性和可维护性。通过示例对比,可以看出OOP使C++代码结构更清晰,特别是在大型项目中,能有效提高开发效率和软件质量。
20 1
|
21天前
|
C++
C++代码来计算一个点围绕另一个点旋转45度后的坐标
C++代码来计算一个点围绕另一个点旋转45度后的坐标
39 0
|
21天前
|
C++
Resharper c++ 使用Enter自动补全代码
Resharper c++ 使用Enter自动补全代码
28 0
|
28天前
|
监控 编译器 C++
【代码讲解】【C/C++】获取文件最后修改的时间(系统时间)
【代码讲解】【C/C++】获取文件最后修改的时间(系统时间)
32 0
|
2月前
|
C++ 运维
开发与运维编译问题之在C++中在使用std::mutex后能自动释放锁如何解决
开发与运维编译问题之在C++中在使用std::mutex后能自动释放锁如何解决
46 2