gcc编译器和gdb调试器

本文详细介绍了GCC编译器的工作原理,包括预处理、编译、汇编和连接等阶段,以及静态链接和动态链接的区别。同时,深入探讨了GDB调试器的使用方法,如设置断点、单步调试、查看调用栈和打印变量等关键操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

gcc:编译器

将高级语言(C语言)程序编译成为机器可识别的指令代码
编译过程:

预处理:去掉注释,展开所有代码
编译:语义、语法纠错,将代码解释成为汇编代码
汇编:将汇编代码解释成为机器指令代码
连接:链接代码库以及所有的目标文件,生成可执行程序
库文件:大佬实现一些常用的功能接口,为了防止每次编译耗费大量时间,因此将这些接口代码进行编译汇编,并且将汇编完成的代码存储到一个文件中,这个文件就叫做库文件。
这时候如果想用库函数,就需要包含头文件中,因为头文件中声明这个函数的存在,这时候编译器在头文件中检测到这个声明,就知道有这个函数的实现,就不会报错。
最终连接生成可执行程序的时候,因为要具体实现让CPU处理指令,因此就必须将这些接口的具体实现拿过来。

gcc的链接方式:

静态链接:链接静态库,连接时将库中代码写入到可执行程序中

优点:运行不依赖库的存在
缺点:占用资源较多,并且如果大量的程序静态链接,会在内存中造成代码冗余

动态链接:连接动态库,链接时,只记录接口的位置符号信息,并不拷贝代码;

优点:占用资源少,在内存中大量程序可以共享使用(共享库)
缺点:运行时需要依赖库的存在(运行时库)

gcc编译器默认的链接方式:动态链接

gdb调试器

#include <stdio.h>
#include <unistd.h>
#include <string.h>

void func(){
  printf("nihao!!\n");
  printf("nihao!!\n");
  printf("nihao!!\n");
}

int main(int argc,char *argv[]) 

//运行程序时,运行程序名称后以空格间隔起来的数据,就是程序的运行参数;

{
  int i;
  printf("--------\n");
  for(i=0;i<argc;i++){
    printf("argv[%d]=[%s]\n",i,argv[i]);
  }
  func();
  printf("hello world!\n");
  char* ptr = NULL;
  memcpy(ptr,"nihao!!",7);
  printf("hello %s\n",ptr);
  return 0;
}
调试一个程序的前提:生成debug版本程序,向程序中添加调试符号信息

linux下gcc默认生成的程序是release版本程序
需要加上-g选项,生成debug版本程序
gcc -g main.c -o main

gdb加载程序

gdb ./main
gdb -> file ./main

获取运行参数,并运行程序

r -a -l -s -t

最常见的调试操作有哪些?

断点

b(break):打断点

b file:linne:指定行打断点
b function_name :给函数打断点

i(info):查看调试信息

i b :查看断点信息

d(delete) :删除断点

d b_id(断点编号)

单步调试

start:开始逐步调试
l(liat):查看调试行附近的代码

l file:line 查看指定行代码

n(next) 下一步:不进入函数,直接将函数运行
s(step) 下一步:跟踪进入函数
until 直接运行到指定行

until file:line

watch 变量监控

watch var name

c(continue) 继续开始运行

打印变量内容

p(print) 打印变量内容

p var_name

查看调用栈信息

bt 快速定位程序崩溃位置

make/makefile

make/makefile:项目自动化构建工具

makefile: 普通的文本文件,记录了项目的构建流程
make: 一个解释程序,到当前执行make命令的目录下寻找makefile文件,并且对makefile中记录的项目构建规则进行解释执行。

makefile编写规则

目标对象:依赖对象

main:main.c child.c

[tab]命令操作

   gcc main.c child.c -o main

make执行规则

1.解释执行时,在makefile中寻找目标对象(只寻找第一个目标对象),找到目标对象后,执行命令操作
如果有目标对象,判读目标对象是否存在

如果目标对象不存在:执行命令操作生成目标对象
如果目标对象已经存在:判断是否有依赖对象

没有依赖对象:直接报错(目标最新),不需要重新生成
如果有依赖对象:判断依赖对象是否存在?

依赖对象存在:通过目标对象和依赖对象的最后一次修改时间判断的是否需要重新执行操作命令,生成目标对象
依赖对象不存在:make继续在makefile中寻找依赖对象的生成规则,生成依赖对象,进而在生成目标对象

预定义变量:

$@: 目标对象

$^: 所有依赖对象

$<: 依赖对象中的第一个

伪对象:目标对像每次都要重新执行(不管是否存在,是否更新)

声明伪对象 .PHONY


git:项目版本控制工具





进度条程序
\r 和\n

printf(hello)—不带有\n时,数据先被写入到缓冲区中,等到缓冲区满了/刷新缓冲区,才会被写入文件

\n在操作的文件为终端显示文件,不仅具备换行作用,还具有刷新缓冲区的作用(仅仅针对终端显示文件)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值