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

目录
相关文章
|
2月前
|
安全 编译器 程序员
【C++篇】C++类与对象深度解析(六):全面剖析拷贝省略、RVO、NRVO优化策略
【C++篇】C++类与对象深度解析(六):全面剖析拷贝省略、RVO、NRVO优化策略
54 2
|
1月前
|
算法 安全 C++
提高C/C++代码的可读性
提高C/C++代码的可读性
48 4
|
1月前
|
Ubuntu Linux Shell
C++ 之 perf+火焰图分析与调试
【11月更文挑战第6天】在遇到一些内存异常的时候,经常这部分的代码是很难去进行分析的,最近了解到Perf这个神器,这里也展开介绍一下如何使用Perf以及如何去画火焰图。
|
2月前
|
存储 程序员 编译器
简述 C、C++程序编译的内存分配情况
在C和C++程序编译过程中,内存被划分为几个区域进行分配:代码区存储常量和执行指令;全局/静态变量区存放全局变量及静态变量;栈区管理函数参数、局部变量等;堆区则用于动态分配内存,由程序员控制释放,共同支撑着程序运行时的数据存储与处理需求。
147 21
|
2月前
|
Ubuntu Linux Shell
C++ 之 perf+火焰图分析与调试
【10月更文挑战第8天】在遇到一些内存异常的时候,经常这部分的代码是很难去进行分析的,最近了解到Perf这个神器,这里也展开介绍一下如何使用Perf以及如何去画火焰图。
|
2月前
|
安全 测试技术 C++
【C++篇】从零实现 C++ Vector:深度剖析 STL 的核心机制与优化2
【C++篇】从零实现 C++ Vector:深度剖析 STL 的核心机制与优化
70 6
|
2月前
|
安全 测试技术 C++
【C++篇】从零实现 C++ Vector:深度剖析 STL 的核心机制与优化1
【C++篇】从零实现 C++ Vector:深度剖析 STL 的核心机制与优化
76 7
|
2月前
|
Linux C语言 C++
vsCode远程执行c和c++代码并操控linux服务器完整教程
这篇文章提供了一个完整的教程,介绍如何在Visual Studio Code中配置和使用插件来远程执行C和C++代码,并操控Linux服务器,包括安装VSCode、安装插件、配置插件、配置编译工具、升级glibc和编写代码进行调试的步骤。
338 0
vsCode远程执行c和c++代码并操控linux服务器完整教程
|
3月前
|
C++
继续更新完善:C++ 结构体代码转MASM32代码
继续更新完善:C++ 结构体代码转MASM32代码
|
3月前
|
C++ Windows
HTML+JavaScript构建C++类代码一键转换MASM32代码平台
HTML+JavaScript构建C++类代码一键转换MASM32代码平台