Jason Zhou的Coding之路 凡是过往皆为序章

C/C++ 基础-GCC编译和gdb等基础

2020-08-02

最近在看操作系统,有些地方总需要写写代码尝试一下。但好多东西都不是在 windows 下尝试的,没办法必须使用 Linux 环境下的 C++。总归 GCC/gdb 的相关基础是要提上日程的,这里通过网上看的东西,稍微整理一些入门,增加一些入门知识,也备不时之需。

GCC相关内容

什么是gcc和g++

  • GCC 是指 GNU Compiler Collection,是一种支持多种语言的编译器。GNU 编译套件包括包括 C/C++, Objective-C, Fortran, Java, Ada 和 Go 语言等。
  • 对 C 语言 gcc 调用 C compiler,对 C++则 g++调用 C++ compiler。
  • 两者区别:
    • .cpp.c 对于 gcc 时不一样的,对 g++都作为 .cpp 文件编译
    • g++会自动链接标准库 STL,gcc 不会
    • gcc 编译 .c 时预定义宏比较少。gcc 编译 .cpp 和 g++编译 .c.cpp 时都会添加额外的宏。
    • gcc 编译 c++为了使用 STL,可添加参数-lstdc++。但两者并不只是这个差距

下面是其他编译器或解释器名称。C(gcc), C++(g++), Java(编译器:gcj, 解释器:gij), Objective-C(gobjc)

gcc的特点

  • 可移植性,支持多种平台常见的 ARM,X86 等。
  • gcc 可实现本地编译和跨平台交叉编译。
  • 支持语言多。
  • gcc 模块化设计,可以添加新的语言和新的 CPU 架构支持。
  • gcc 自由软件。GNU。

gcc编译过程

  • 主要分为四个步骤:预处理 Pre-Processing,编译 Compiling,汇编 Assembling,链接 Linking,过程如下图。
  • 预处理:将头文件、宏等进行展开,去除注释等。不会有语法检查。代码会大量扩充。
  • 编译:根据不同语言编译器,进行编译,生成汇编代码。会检查语法。
  • 汇编:生成目标代码。
  • 链接:将程序需要的目标文件进行链接生成可执行文件。

gcc常用选项

选项名称 作用
-o 产生目标(.i, .s, .o可执行文件等)
-O/-O2 优化编译、链接,执行效率会高,编译会慢
-E 运行 C 预编译器, 产生.i
-S 产生汇编文件后停止,.s
-c 取消链接步骤,仅编译源码,并在最后生成目标文件
-Wall 让 gcc 对源码有问题的地方发出警告
-I [dir] 将 dir 目录加入到头文件搜索目录路径中
-L [dir] 将 dir 目录加入到库的搜索目录路径中
-lib 链接 lib 库
-g 在目标文件中嵌入调试信息,例如 gdb 之类的
-v gcc 在执行过程中的详细过程,gcc 及相关程序版本号

使用的代码示例

gcc -E hello.c -o hello.i	对hello.c文件进行预处理,生成了hello.i 文件
gcc -S hello.i -o hello.s	对预处理文件进行编译,生成了汇编文件
gcc -c hello.s -o hello.o	对汇编文件进行编译,生成目标文件,不链接不包含子程序文件
gcc hello.o -o hello 		对目标文件进行链接,生成可执行文件,不给名字则为x.out
gcc hello.c -o hello 		直接编译链接成可执行目标文件
gcc -c hello.c 或 gcc -c hello.c -o hello.o 编译生成可重定位目标文件
gcc -Wall bad.c -o bad		提示编译器报出警告错误

多文件联合编译和分别独立编译

g++ linkHello.c test.c -o main 多个文件联合编译, 可以不添加.h库文件, 但是相应的.c文件要编译

分别独立编译,使得未修改文件无需再编译
g++ -c linkHello.c -o linkHello.o	编译linkHello.c生成不链接的目标文件.o
g++ -c test.c -o main.o				编译test.c生成不链接的目标文件.o
g++ linkHello.o mian.o -o main		链接的两个目标文件生成可执行文件

外部库的调用

  • 静态库.a:链接时将库的代码链接到可执行文件中,运行时每个程序包含一份,不在需要静态库。
  • 动态库 .so.sa:运行时才去链接到共享库代码,多个程序共享使用,减小程序体积。
  • 一般的库文件所在位置:/usr/include 及其期目录下的 include, /usr/local/include, /usr/lib, /usr/local/lib, /lib。

生成静态库和共享库(动态库)

  • 静态库:先生成目标文件 .o,再打包 ar rcs hellolib.a hello.o,将其打包为 hellolib.a。ar 是 GUN 归档工具,rcs 表示 replace and create(会替换已存在的 libhello.a 文件)。
  • 静态库使用方法:编译时把它加入进去就行 gcc hellolib.a test.c -o hello
  • 动态库生成方法:也需要先生成目标文件 .o, gcc -shared -fPIC hello.o -o libhello.so。-shared 表示生成共享库格式, fPIC 表示产生位置无关码,表示与加载的内存地址无关。
  • 动态库使用:方法 1. 将动态库放到/usr/lib 目录。方法 2. ~/.bash_profile 中配置 LD_LIBRARY_PATH 变量。方法 3. 配置/etc/ld.so.conf,配置后调用 ldconfig 更新 ld.so.cache。

库搜索路径

  • 搜索先后原则:从左到右搜索-l 指定的目录->环境变量指定的目录(头文件 C_INCLUDE_PATH, 库 LIBRARY_PATH)->系统指定的目录。

GDB相关内容

GDB及其功能

  • Unix 及类 Unix 下的调试工具。
  • 主要包括四方面的功能:
    • 启动程序,按照自定义要求启动程序。
    • 设置断点。
    • 检查程序停止时发生的情况。
    • 改变程序。

GDB使用

GDB运行

  • 在编译过程中和运行过程中有设置。
    g++ -g -std=c++11 linkHello.c test.c -o main.out    -g嵌入调试信息 -std=执行标准
    gdb main.out                                        调试
    

常用的命令

运行指令

  • run 简写 r:运行程序,如设置断点则停止运行等待下一步命令。
  • continue 简写 c:继续执行,直到下一个断点。
  • next 简写 n:单步执行,不进入函数体内部直接调用。
  • step 简写 s:单步执行,进入函数体内部。
  • until 简写 u:运行到循环体退出循环。循环体有断点,断点仍然会停。
  • until+行号 :运行到某一行,可以跳出循环。
  • finish:运行程序直到当前函数返回,并打印函数返回时的堆栈地址和返回值以及参数值等信息。
  • call 函数(参数):调用程序中可见的函数,并传递“参数”。
  • quit 简写 q:退出 gdb

设置断点

  • break n 简写 b n:在第 n 行处设置断点(可在行号前设置代码路径和代码名称)
  • b fn1 if a>b:条件断点设置
  • break func:在函数 func()的入口处设置断点,如:break cb_button
  • delete n:删除第 n 个断点
  • disable n:暂停第 n 个断点,可以在启动 enable
  • enable n:开启第 n 个断点
  • clear n:清除第 n 行的断点
  • info breakpoints 简写 info b:显示当前程序的断点设置情况
  • delete breakpoints:清除所有断点

查看源代码

  • list 行号 简写 l:列出程序源代码,默认前后共十行。
  • list 函数名 :显示函数名所在的源代码
  • list:不带阐述,运行时显示当前所在行(程序断点位置,上次 list 后的位置)的前后共十行。运行前则显示程序开始位置之后的 10 行。

打印

  • print 表达式 简写 p:可以答应被测试程序的有效表达式。包括数字,变量甚至调用函数。
  • display 表达式 :display 命令设置表达式后,每次单步执行指令后,紧接着输出被设置的表达式。
  • watch 表达式 :设置监视点,一旦被监视的“表达式”改变,gdb 强行终止被调试程序。
  • whatis:查询变量或函数
  • info function:查询函数
  • 扩展 info locals:显示当前堆栈页的所有变量

查询运行信息

  • where/bt:当前运行的堆栈列表;
  • bt backtrace:显示当前调用堆栈
  • up/down:改变堆栈显示的深度
  • set args:参数:指定运行时的参数
  • show args:查看设置好的参数
  • info program:来查看程序的是否在运行,进程号,被暂停的原因。

参考链接:

  1. Linux 编译:gcc 入门
  2. g++以及 gcc 的区别
  3. Linux 下 GDB 调试指令汇总

Similar Posts

Comments