赞
踩
目录
(7)gcc/g++ 优化标识 -O1 -O2 -O3 -Os -Ofast -Og的作用
gcc编译C源码有四个步骤:
选项 | 含义 |
-o 可执行文件名 | 指定生成的输出文件名,比如可执行文件名或者二进制文件名等 |
-E | 只运行 C 预编译器,即只执行头文件展开、宏替换和注释去掉的工作:gcc -E hello.c -o hello.i |
-S | c文件变成汇编文件(将C代码转换为汇编代码):gcc -S hello.i -o hello.s |
-c | 编译但是不链接。只编译并生成目标文件。gcc -c hello.s -o hello.o |
-std=c++11 | 语言标准,如-std=c++11表示采用2011 ISO C++标准 |
-g | 在目标文件中嵌入调试信息,生成供调试用的可执行文件,以便gdb之类的调试程序调试,GNU 调试器可利用该信息。由于文件中包含了调试信息因此运行效率很低,且文件也大不少,因此一般调试时可加此选项,正式发布时可不加。 |
-O1 | 编译器优化级别控制。默认不做优化,即-O0。使用-O1, -O2, -O3,编译器优化程度依次增加,优化越高,编译时用时越长,但运行时效率越高。 |
-Wall | 打开所有警告,生成所有警告信息 |
-w | 不生成任何警告信息。 |
-shared | 生成共享目标文件。生成动态库时需要用到。 |
-static | 禁止使用动态库,优先使用动态库。 |
-I dir | 大写的i。指定头文件所在的文件夹。dir是路径,表示把dir加到头文件搜索路径中。这个选项很重要,特别是在使用第三方库的时候,以及cpp文件与h文件不再同一个路径下的时候 |
-l | -l,小写的l,指定所使用到的函数库名。 链接到某个库,比如-lnetcdf_c++4 |
-L dir | -L,大写的l,指定函数库所在的文件夹。可以与-l配合使用,告诉编译器去哪里找到链接库 |
-fPIC | fPIC 的全称是 Position Independent Code, 用于生成位置无关代码。可以大写-fPIC,也可以小写-fpic。 (1)不加 fPIC 也可以生成 .so 文件,但是对于源文件有要求,例如因为不加 fPIC 编译的 so 必须要在加载到用户程序的地址空间时重定向所有表目,所以在它里面不能引用其它地方的代码。因此建议编译时加上这个选项。 (2)不用此选项的话编译后的文件(比如二进制目标文件、动态库文件等)是位置相关的,所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。 (3)不加这个选项更消耗内存,但是不加 fPIC 编译的 so 文件的优点是加载速度比较快。 |
-D 宏名 | 相当于给程序中加了一个宏 比如-D name ,预定义一个名为name 的宏,值为1。 比如-D DEBUG,预定义一个名为DEBUG的宏,值为1。 -Dname =definition,预定义名为name ,值为definition 的宏。 |
第1种:四步合一
直接由源代码编译得到可执行文件
单个c文件:gcc main.c -o main
多个c文件:gcc main.c data.c tool.c -o main
第2种:源文件→二进制文件→可执行文件
- # 由cpp文件汇编生成的二进制目标文件
- g++ -c -O2 -fPIC DataTool.cpp -o DataTool.o
- g++ -c -O2 -fPIC DealTool.cpp -o DealTool.o
- g++ -c -O2 -fPIC main.cpp -o main.o
-
-
- # 编译生成test_demo
- g++ -O2 -fPIC main.o DataTool.o DealTool.o -o test_demo -ldl -lrt
- -lz 是link libz,链接压缩库(Z)
- -lrt 实时库(real time):shm_open系列
- -lm 是link libm,链接数学库(math)
- -lc 是link libc,链接标准C库(C lib)
- -ldl 是显式加载动态库的动态函数库,如果你的程序中使用dlopen、dlclose等
- -lnsl 需要链接libnsl.so, libnsl.so是C网络服务的库
- -lclntsh 需要链接libclntsh.so,是orcale客户端编译的时候需要用到的一个库
- -lpthread 线程库
- -lsnmp++ 网络管理库
- -locci 是指Oracle C++ Call Interface对应的动态库,(OCCI)驱动程序
linux系统的C编译器为gcc,它是GNU推出的功能强大的编译工具,因为UNIX系统的编译器为cc,所以在Linux系统还保留一个链接cc,用于和UNIX的向后兼容。
gcc是GNU C Compiler的缩写。gcc(GNU C Compiler)编译器的作者是Richard Stallman,也是GNU项目的奠基者。
(1)常用习惯与误区说明
值得一提的是,实际使用中我们更习惯使用 gcc 指令编译 C 语言程序,用 g++ 指令编译 C++ 代码。需要强调的一点是,这并不是 gcc 和 g++ 的区别,gcc 指令也可以用来编译 C++ 程序,同样 g++ 指令也可以用于编译 C 语言程序。
(2)编译c或者cpp时的区别
gcc和g++都可以编译c++代码
(3)是否定义__cplusplus宏
(1)-O,-O1
这两个命令的效果是一样的,目的都是在不影响编译速度的前提下,尽量采用一些优化算法降低代码大小和可执行代码的运行速度。并开启如下的优化选项:
-fauto-inc-dec -fbranch-count-reg -fcombine-stack-adjustments -fcompare-elim -fcprop-registers -fdce -fdefer-pop -fdelayed-branch -fdse -fforward-propagate -fguess-branch-probability -fif-conversion2 -fif-conversion -finline-functions-called-once -fipa-pure-const -fipa-profile -fipa-reference -fmerge-constants -fmove-loop-invariants -freorder-blocks -fshrink-wrap -fshrink-wrap-separate -fsplit-wide-types -fssa-backprop -fssa-phiopt -fstore-merging -ftree-bit-ccp -ftree-ccp -ftree-ch -ftree-coalesce-vars -ftree-copy-prop -ftree-dce -ftree-dominator-opts -ftree-dse -ftree-forwprop -ftree-fre -ftree-phiprop -ftree-sink -ftree-slsr -ftree-sra -ftree-pta -ftree-ter -funit-at-a-time
(2)-O2
该优化选项会牺牲部分编译速度,除了执行-O1所执行的所有优化之外,还会采用几乎所有的目标配置支持的优化算法,用以提高目标代码的运行速度
-fthread-jumps -falign-functions -falign-jumps -falign-loops -falign-labels -fcaller-saves -fcrossjumping -fcse-follow-jumps -fcse-skip-blocks -fdelete-null-pointer-checks -fdevirtualize -fdevirtualize-speculatively -fexpensive-optimizations -fgcse -fgcse-lm -fhoist-adjacent-loads -finline-small-functions -findirect-inlining -fipa-cp -fipa-cp-alignment -fipa-bit-cp -fipa-sra -fipa-icf -fisolate-erroneous-paths-dereference -flra-remat -foptimize-sibling-calls -foptimize-strlen -fpartial-inlining -fpeephole2 -freorder-blocks-algorithm=stc -freorder-blocks-and-partition -freorder-functions -frerun-cse-after-loop -fsched-interblock -fsched-spec -fschedule-insns -fschedule-insns2 -fstrict-aliasing -fstrict-overflow -ftree-builtin-call-dce -ftree-switch-conversion -ftree-tail-merge -fcode-hoisting -ftree-pre -ftree-vrp -fipa-ra
(3)-O3
该选项除了执行-O2所有的优化选项之外,一般都是采取很多向量化算法,提高代码的并行执行程度,利用现代CPU中的流水线,Cache等
- -finline-functions // 采用一些启发式算法对函数进行内联
- -funswitch-loops // 执行循环unswitch变换
- -fpredictive-commoning //
- -fgcse-after-reload //执行全局的共同子表达式消除
- -ftree-loop-vectorize //
- -ftree-loop-distribute-patterns
- -fsplit-paths
- -ftree-slp-vectorize
- -fvect-cost-model
- -ftree-partial-pre
- -fpeel-loops
- -fipa-cp-clone options
(4)-Os
这个优化标识和-O3有异曲同工之妙,当然两者的目标不一样,-O3的目标是宁愿增加目标代码的大小,也要拼命的提高运行速度,但是这个选项是在-O2的基础之上,尽量的降低目标代码的大小,这对于存储容量很小的设备来说非常重要。为了降低目标代码大小,会禁用下列优化选项,一般就是压缩内存中的对齐空白(alignment padding)
(5)-Ofast
该选项将不会严格遵循语言标准,除了启用所有的-O3优化选项之外,也会针对某些语言启用部分优化。如:-ffast-math ,对于Fortran语言,还会启用下列选项
- -fno-protect-parens
- -fstack-arrays
(6)-Og
优化调试体验。 -Og应该是标准edit-compile-debug周期的优化级别选择,在保持快速编译和良好调试体验的同时,提供合理的优化级别。用于生成可调试代码,因为某些收集调试信息的编译器通道在以下位置被禁用 -O0。像-O0 -Og完全禁用了许多优化过程,因此控制它们的单个选项无效。除此以外-Og 使所有 -O1 优化标志,但那些可能会干扰调试的标志除外:
- -fbranch-count-reg
- -fdelayed-branch
- -fdse
- -fif-conversion
- -fif-conversion2
- -finline-functions-called-once
- -fmove-loop-invariants
- -fssa-phiopt
- -ftree-bit-ccp
- -ftree-dse
- -ftree-pta
- -ftree-sra
Linux环境C++编译报错:undefined reference to `std::ios_base::Init::Init()
问题描述
- /root/gcc11.3/include/c++/11.3.0/iostream:74:对‘std::ios_base::Init::Init()’未定义的引用
- /root/gcc11.3/include/c++/11.3.0/iostream:74:对‘std::ios_base::Init::~Init()’未定义的引用
Linux Linux环境C++编译报错 undefined reference to `std::i
出现情况:在Linux系统,用gcc(C编译器)编译C++程序,会报标题的错误。
原因是用gcc编译c++程序时,应当链接的库文件为libstdc++.so,而不是默认的libc.so,因此需要用-lstdc++参数指明,否则会在链接时发生错误。
如: gcc myfirst.cpp -lstdc++
gcc mem_map.cpp mmap_w.cpp -o mmap_w -lstdc++
或者使用g++命令
g++ mem_map.cpp mmap_w.cpp -o mmap_w
uttools-libhelper.cxx:(.text+0x23cd):对‘utadapter::ut_initxxxxx未定义的引用
collect2: 错误:ld 返回 1
总结一下C++链接错误“对函数或变量未定义的引用”解决办法:
undefined reference to symbol 'pthread_create@@GLIBC_2.2.5'
这个错误信息通常表示在链接时找不到对应的线程库。解决办法是在编译时添加 -pthread 选项来链接线程库。以下是一个示例代码:
gcc -pthread your_code.c -o your_output
/usr/bin/ld: cannot find -lstdc++
需要安装gcc和g++
动态库名字格式 libxxx.so
/lib64/libstdc++.so.6: version `CXXABI_1.3.9' not found (required by............)
问题描述
原因分析
gcc动态库版本过老
解决办法
a. 查看gcc动态库版本
strings /lib64/libstdc++.so.6 | grep CXXABI
发现CXXABI最高版本只有1.3.7,没有1.3.9的。解决办法是高版本gcc的动态库替换老版本gcc的动态库。
查看libstdc++.so.6属性
ls -l /lib64/libstdc++.so.6
发现libstdc++.so.6是个软连接,是直接链接到libstdc++.so.6.0.19上去的,而libstdc++.so.6.0.19是老版本的动态库,所以下面要做的就是将libstdc++.so.6连接到新版本的动态库上去。
b.查找编译gcc时生成的最新动态库
执行以下命令,查找编译gcc时生成的最新动态库
find / -name "libstdc++.so.*"
其中/root/gcc11.3/lib64/libstdc++.so.6.0.29是我们新版本的动态库
查看其动态库,能否满足我们的要求
strings /root/gcc11.3/lib64/libstdc++.so.6.0.29 | grep CXXABI
可以看到CXXABI有1.3.9的,满足要求。
如果系统中没有相应的libstdc++.so.x.x.x文件或者不满足我们的要求,可以去下最新版本的RPM resource libstdc
http://www.rpmfind.net/linux/rpm2html/search.php?query=libstdc&submit=Search+...&system=centos&arch=
c. 将上面的最新动态库复制到/lib64/目录下
cp /root/gcc11.3/lib64/libstdc++.so.6.0.29 /lib64/
d. 重新将libstdc++.so.6连接到libstdc++.so.6.0.29上去
- cd /lib64
- rm -rf libstdc++.so.6
- ln -s libstdc++.so.6.0.29 libstdc++.so.6
e. 默认动态库升级完成。重新运行以下命令检查动态库
strings /lib64/libstdc++.so.6 | grep 'CXXABI'
可以看到新的动态库确实链接上去了
问题提示
linux下调用动态库.so文件时提示:cannot open shared object file: No such file or directory
在使用第三方so库的时候需要引入到自己的项目中,在编译阶段是没问题的,但是一旦运行会报以下错误:error while loading shared libraries: xxxxxxx.so: cannot open shared object file: No such file or directory
查看该可执行文件需要的库是否存在
比如可执行文件名字叫test
ldd test
执行以上命令,它需要调用哪些动态库,以及该动态库是否存在
解决办法
设置LD_LIBRARY_PATH这个环境变量
由于操作系统在运行程序过程中的package搜索路径依赖于LD_LIBRARY_PATH这个环境变量,所以检查是否包括该路径:
export | grep LD_LIBRARY_PATH
如果没有,则添加:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:动态库所在目录路径
问题提示
mongo: error while loading shared libraries: libcrypto.so.10: cannot open shared object file: No such file or directory
查看缺少的库文件
ldd /data/usr/mongodb/bin/mongod
/lib64 目录下少了文件:libcrypto.so.10、libssl.so.10
查看宿主机:
- ll /lib64/libcrypto.so.1*
-
- ll /lib64/libssl.so*
发现libcrypto.so.10是软连接,真正的文件是libcrypto.so.1.0.2k
解决方案
第①种:创建软链接
如果有libcrypto.so.1.0.2k 则在容器中创建软连接就可以了
第②种:直接复制过来
复制文件到当前目录。
懒得复制原名再创建软连接了,直接复制成新的名称
- cp /lib64/libcrypto.so.1.0.2k libcrypto.so.10
-
- cp /lib64/llibssl.so.1.0.2k libssl.so.10
问题描述
./testAPI: error while loading shared libraries: libNanoQuote.so: file too short
原因:拷贝的libNanoQuote.so的文件大小是0,于是出现了这个问题
解决办法:将正确大小的动态库libNanoQuote.so文件拷贝过来就好
end
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。