当前位置:   article > 正文

【c/c++】gcc/g++知识和常见问题解决方案_gcc10 c++执行问题

gcc10 c++执行问题

目录

(1)c/c++编译过程

(2)gcc/g++常用参数

(3)编译举例

(4)gcc常连接的动态库

(5)linux下cc与gcc的关系

(6)gcc和g++的区别

(7)gcc/g++ 优化标识 -O1 -O2 -O3 -Os -Ofast -Og的作用

(8)编译常见报错解决方案

1.gcc编译c++程序报错

2.编译c++出现对xxx未定义的引用

3.找不到对应的线程库

4.cannot find -lstdc++

5.linux下动态库名字格式不对

(9)运行可执行文件常见问题解决办法

1.某版本的CXXABI找不到

2.调用动态库找不到.so库

3.缺少libcrypto.so.10库

4.file too short问题


(1)c/c++编译过程

gcc编译C源码有四个步骤:

  1. 预处理(也叫预编译):宏定义展开、头文件展开、条件编译等,同时将代码中的注释删除,这里并不会检查语法。
  2. 编译:检查语法,将预处理后文件编译生成汇编文件。在这个阶段中,gcc首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc把代码翻译成汇编语言。
  3. 汇编:将汇编文件生成目标文件(二进制文件)。
  4. 链接:C语言写的程序是需要依赖各种库的,所以编译之后还需要把库链接到最终的可执行程序中去。

(2)gcc/g++常用参数

选项

含义

-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 的宏。

(3)编译举例

第1种:四步合一

直接由源代码编译得到可执行文件

单个c文件:gcc main.c -o main

多个c文件:gcc main.c data.c tool.c -o main

第2种:源文件→二进制文件→可执行文件

  1. # 由cpp文件汇编生成的二进制目标文件
  2. g++ -c -O2 -fPIC DataTool.cpp -o DataTool.o
  3. g++ -c -O2 -fPIC DealTool.cpp -o DealTool.o
  4. g++ -c -O2 -fPIC main.cpp -o main.o
  5. # 编译生成test_demo
  6. g++ -O2 -fPIC main.o DataTool.o DealTool.o -o test_demo -ldl -lrt

(4)gcc常连接的动态库

  1. -lz 是link libz,链接压缩库(Z)
  2. -lrt 实时库(real time):shm_open系列
  3. -lm 是link libm,链接数学库(math)
  4. -lc 是link libc,链接标准C库(C lib)
  5. -ldl 是显式加载动态库的动态函数库,如果你的程序中使用dlopen、dlclose等
  6. -lnsl 需要链接libnsl.so, libnsl.so是C网络服务的库
  7. -lclntsh 需要链接libclntsh.so,是orcale客户端编译的时候需要用到的一个库
  8. -lpthread 线程库
  9. -lsnmp++ 网络管理库
  10. -locci 是指Oracle C++ Call Interface对应的动态库,(OCCI)驱动程序

(5)linux下cc与gcc的关系

linux系统的C编译器为gcc,它是GNU推出的功能强大的编译工具,因为UNIX系统的编译器为cc,所以在Linux系统还保留一个链接cc,用于和UNIX的向后兼容。

gcc是GNU C Compiler的缩写。gcc(GNU C Compiler)编译器的作者是Richard Stallman,也是GNU项目的奠基者。

(6)gcc和g++的区别

(1)常用习惯与误区说明

值得一提的是,实际使用中我们更习惯使用 gcc 指令编译 C 语言程序,用 g++ 指令编译 C++ 代码。需要强调的一点是,这并不是 gcc 和 g++ 的区别,gcc 指令也可以用来编译 C++ 程序,同样 g++ 指令也可以用于编译 C 语言程序。

(2)编译c或者cpp时的区别

  • 对于gcc来说,后缀为.c的,gcc 把它当作是 c程序,后缀为.cpp 的,会认为是C++程序。
  • 对于g++来说,无论是.c还是.cpp,都当做c++程序。

gcc和g++都可以编译c++代码

  • 直接用g++
  • 用gcc,但是需要链接c++标准库:gcc -lstdc++。

(3)是否定义__cplusplus宏

  • __cplusplus这个宏只是标志着编译器将会把代码按c还是C++语法来解释。
  • gcc不会定义__cplusplus 宏,而g++会。如果后缀为.c,并且采用gcc编译器,则该宏就是未定义的,否则如果是g++,就是已定义。

(7)gcc/g++ 优化标识 -O1 -O2 -O3 -Os -Ofast -Og的作用

(1)-O,-O1

这两个命令的效果是一样的,目的都是在不影响编译速度的前提下,尽量采用一些优化算法降低代码大小和可执行代码的运行速度。并开启如下的优化选项:

  1. -fauto-inc-dec
  2. -fbranch-count-reg
  3. -fcombine-stack-adjustments
  4. -fcompare-elim
  5. -fcprop-registers
  6. -fdce
  7. -fdefer-pop
  8. -fdelayed-branch
  9. -fdse
  10. -fforward-propagate
  11. -fguess-branch-probability
  12. -fif-conversion2
  13. -fif-conversion
  14. -finline-functions-called-once
  15. -fipa-pure-const
  16. -fipa-profile
  17. -fipa-reference
  18. -fmerge-constants
  19. -fmove-loop-invariants
  20. -freorder-blocks
  21. -fshrink-wrap
  22. -fshrink-wrap-separate
  23. -fsplit-wide-types
  24. -fssa-backprop
  25. -fssa-phiopt
  26. -fstore-merging
  27. -ftree-bit-ccp
  28. -ftree-ccp
  29. -ftree-ch
  30. -ftree-coalesce-vars
  31. -ftree-copy-prop
  32. -ftree-dce
  33. -ftree-dominator-opts
  34. -ftree-dse
  35. -ftree-forwprop
  36. -ftree-fre
  37. -ftree-phiprop
  38. -ftree-sink
  39. -ftree-slsr
  40. -ftree-sra
  41. -ftree-pta
  42. -ftree-ter
  43. -funit-at-a-time

(2)-O2

该优化选项会牺牲部分编译速度,除了执行-O1所执行的所有优化之外,还会采用几乎所有的目标配置支持的优化算法,用以提高目标代码的运行速度

  1. -fthread-jumps
  2. -falign-functions -falign-jumps
  3. -falign-loops -falign-labels
  4. -fcaller-saves
  5. -fcrossjumping
  6. -fcse-follow-jumps -fcse-skip-blocks
  7. -fdelete-null-pointer-checks
  8. -fdevirtualize -fdevirtualize-speculatively
  9. -fexpensive-optimizations
  10. -fgcse -fgcse-lm
  11. -fhoist-adjacent-loads
  12. -finline-small-functions
  13. -findirect-inlining
  14. -fipa-cp
  15. -fipa-cp-alignment
  16. -fipa-bit-cp
  17. -fipa-sra
  18. -fipa-icf
  19. -fisolate-erroneous-paths-dereference
  20. -flra-remat
  21. -foptimize-sibling-calls
  22. -foptimize-strlen
  23. -fpartial-inlining
  24. -fpeephole2
  25. -freorder-blocks-algorithm=stc
  26. -freorder-blocks-and-partition -freorder-functions
  27. -frerun-cse-after-loop
  28. -fsched-interblock -fsched-spec
  29. -fschedule-insns -fschedule-insns2
  30. -fstrict-aliasing -fstrict-overflow
  31. -ftree-builtin-call-dce
  32. -ftree-switch-conversion -ftree-tail-merge
  33. -fcode-hoisting
  34. -ftree-pre
  35. -ftree-vrp
  36. -fipa-ra

(3)-O3

该选项除了执行-O2所有的优化选项之外,一般都是采取很多向量化算法,提高代码的并行执行程度,利用现代CPU中的流水线,Cache等

  1. -finline-functions // 采用一些启发式算法对函数进行内联
  2. -funswitch-loops // 执行循环unswitch变换
  3. -fpredictive-commoning //
  4. -fgcse-after-reload //执行全局的共同子表达式消除
  5. -ftree-loop-vectorize  //
  6. -ftree-loop-distribute-patterns
  7. -fsplit-paths
  8. -ftree-slp-vectorize
  9. -fvect-cost-model
  10. -ftree-partial-pre
  11. -fpeel-loops
  12. -fipa-cp-clone options

(4)-Os

这个优化标识和-O3有异曲同工之妙,当然两者的目标不一样,-O3的目标是宁愿增加目标代码的大小,也要拼命的提高运行速度,但是这个选项是在-O2的基础之上,尽量的降低目标代码的大小,这对于存储容量很小的设备来说非常重要。为了降低目标代码大小,会禁用下列优化选项,一般就是压缩内存中的对齐空白(alignment padding)

(5)-Ofast

该选项将不会严格遵循语言标准,除了启用所有的-O3优化选项之外,也会针对某些语言启用部分优化。如:-ffast-math ,对于Fortran语言,还会启用下列选项

  1. -fno-protect-parens
  2. -fstack-arrays

(6)-Og

优化调试体验。 -Og应该是标准edit-compile-debug周期的优化级别选择,在保持快速编译和良好调试体验的同时,提供合理的优化级别。用于生成可调试代码,因为某些收集调试信息的编译器通道在以下位置被禁用 -O0。像-O0 -Og完全禁用了许多优化过程,因此控制它们的单个选项无效。除此以外-Og 使所有 -O1 优化标志,但那些可能会干扰调试的标志除外:

  1. -fbranch-count-reg
  2. -fdelayed-branch
  3. -fdse
  4. -fif-conversion
  5. -fif-conversion2
  6. -finline-functions-called-once
  7. -fmove-loop-invariants
  8. -fssa-phiopt
  9. -ftree-bit-ccp
  10. -ftree-dse
  11. -ftree-pta
  12. -ftree-sra

(8)编译常见报错解决方案

1.gcc编译c++程序报错

Linux环境C++编译报错:undefined reference to `std::ios_base::Init::Init()

问题描述

  1. /root/gcc11.3/include/c++/11.3.0/iostream:74:对‘std::ios_base::Init::Init()’未定义的引用
  2. /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

2.编译c++出现对xxx未定义的引用

uttools-libhelper.cxx:(.text+0x23cd):对‘utadapter::ut_initxxxxx未定义的引用

collect2: 错误:ld 返回 1

总结一下C++链接错误“对函数或变量未定义的引用”解决办法:

  • 函数或变量所在的库,没有添加到link_directories,需要在CMakeLists.txt里面添加。
  • 模板函数或者模板类数据没有实例化,也可能导致这个问题,需要指定模板,对模板函数或模板类做实例化。
  • src子文件夹下的文件需要在CMakeLists.txt里面include,也就是说有可能executable文件link到source或者include文件时没有找到函数或变量所在的文件,所以说它们未定义。因此将函数或变量所在文件添加到source或者include中并link到可执行文件,即可解决。
  • 有时可能是需要连接的库是软链接,需要先重新生成软键,再进行编译。
  • c++类成员函数的定义时未加作用域。

3.找不到对应的线程库

undefined reference to symbol 'pthread_create@@GLIBC_2.2.5'

这个错误信息通常表示在链接时找不到对应的线程库。解决办法是在编译时添加 -pthread 选项来链接线程库。以下是一个示例代码:

gcc -pthread your_code.c -o your_output

4.cannot find -lstdc++

/usr/bin/ld: cannot find -lstdc++

需要安装gcc和g++

5.linux下动态库名字格式不对

动态库名字格式 libxxx.so

(9)运行可执行文件常见问题解决办法

1.某版本的CXXABI找不到

/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上去

  1. cd /lib64
  2. rm -rf libstdc++.so.6
  3. ln -s libstdc++.so.6.0.29 libstdc++.so.6

e. 默认动态库升级完成。重新运行以下命令检查动态库

strings /lib64/libstdc++.so.6 | grep 'CXXABI'

可以看到新的动态库确实链接上去了

2.调用动态库找不到.so库

问题提示

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:动态库所在目录路径

3.缺少libcrypto.so.10库

问题提示

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 

查看宿主机:

  1. ll /lib64/libcrypto.so.1*
  2. ll /lib64/libssl.so*

 发现libcrypto.so.10是软连接,真正的文件是libcrypto.so.1.0.2k 

解决方案

第①种:创建软链接

如果有libcrypto.so.1.0.2k 则在容器中创建软连接就可以了

第②种:直接复制过来

复制文件到当前目录。

懒得复制原名再创建软连接了,直接复制成新的名称

  1. cp /lib64/libcrypto.so.1.0.2k libcrypto.so.10
  2. cp /lib64/llibssl.so.1.0.2k libssl.so.10

4.file too short问题

问题描述

./testAPI: error while loading shared libraries: libNanoQuote.so: file too short

原因:拷贝的libNanoQuote.so的文件大小是0,于是出现了这个问题

解决办法:将正确大小的动态库libNanoQuote.so文件拷贝过来就好


end

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/576855
推荐阅读
相关标签
  

闽ICP备14008679号