gcc常用
1、gcc选项
-I指定头文件搜索路径。
-D编译时定义宏
-L链接时指定库文件搜索路径
-l指定库文件名称
-pipe使用管道,一个程序的输出作为输入直接送给另外一个程序,
而且还可以一直连续下去,不需要临时文件。
2、程序编译过程
预处理->编译->汇编->链接
预处理:C头文件展开,注释删除,宏替代--可以查看头文件详细内容
gcc -E test.c -o test.i
编译
gcc -S test.i -o test.s
1)语法检查
2)编译成汇编语言。
汇编
gcc -c test.s -o test.o
链接
gcc test.o -o test
1)数据段合并。
2)地址回填,地址重定位。
3、常用命令
objdump -dS ;反汇编
ldd 显示可执行文件使用的一些共享函数库
strace 显示命令执行过程
4、编译选项
1)-Wl,--as-needed 和 -Wl,--no-as-needed
GCC/G++提供了 -Wl,--as-needed 和 -Wl,--no-as-needed 两个选项,这两个选项一个是开启特性,一个是取消该特性。
在生成可执行文件的时候,通过 -lxxx 选项指定需要链接的库文件。以动态库为例,如果我们指定了一个需要链接的库,则连接器会在可执行文件的文件头中会记录下该库的信息。而后,在可执行文件运行的时候,动态加载器会读取文件头信息,并加载所有的链接库。在这个过程中,如果用户指定链接了一个毫不相关的库,则这个库在最终的可执行程序运行时也会被加载,如果类似这样的不相关库很多,会明显拖慢程序启动过程。
这时,通过指定 -Wl,--as-needed 选项,链接过程中,链接器会检查所有的依赖库,没有实际被引用的库,不再写入可执行文件头。最终生成的可执行文件头中包含的都是必要的链接库信息。-Wl,--no-as-needed 选项不会做这样的检查,会把用户指定的链接库完全写入可执行文件中。
2)编译警告信息
在编译代码的时候一定要加上-W和-Wall选项,要保证代码中没有任何的warning信息,提高代码的可靠性。-Wall选项意思是编译后显示所有警告,-W选项只显示编译器认为会出现错误的警告。
屏蔽多种类型的告警
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wformat="
#pragma GCC diagnostic ignored "-Wreturn-type"
3)-rdynamic -funwind-tables
使用backtrace和backtrace_symbols的时候,打印栈信息太少。需要指定选项-rdynamic -funwind-tables,即是用动态符号表和展开tables
-rdynamic ld时将动态库的的所有符号都输出到符号表,以便dlopen和backtrace也能调用
backtrace和backtrace_symbols只能打印.dynsym表里的符号/函数,里面的函数都是全局函数。
.symtab包含所有的符号/函数,其中函数包含了全局函数和static函数。也就是说.dynsym是.symtab的子集。
即使指定-rdynamic -funwind-tables,static函数也不会导出到.dynsym中,也不会被backtrace相关函数打印。
参考: