Linux系统上多文件C程序的编译与调试

一、先建立一个头文件add.h

通过vi创建一个add.h,并进行编写该文件,用来存放求和函数add()的声明:

在这里插入图片描述

二、建立一个add.c文件

通过vi创建一个add.c文件,并进行编写,用来存放求和函数add()的实现:

在这里插入图片描述

三、建立一个max.h头文件

通过vi创建一个max.h,并进行编写该文件,用来存放求最大值函数max()的声明:

在这里插入图片描述

四、建立一个max.c文件

通过vi创建一个max.c,并进行编写该文件,用来存放求最大值函数max()的实现:

在这里插入图片描述

五、建立主函数main.c

通过vi创建一个main.c,并进行编写该文件,用来实现求和函数add()和求最大值函数max()这两个函数的功能:

在这里插入图片描述

六、编译

(1)一步编译

通过gcc -o main main.c add.c max.c进行编译,生成可执行文件main:

在这里插入图片描述

(2)两步编译

①先把.c文件转换为二进制指令.o文件

把add.c文件转换为二进制指令add.o文件;把max.c文件转换为二进制指令max.o文件;把main.c文件转换为二进制指令main.o文件:

在这里插入图片描述

②进行链接,生成可执行程序main

在这里插入图片描述

七、makefile和make

makefile文件中的内容描述了如何编译整个工程。makefile文件的作用是管理整个工程。 真正的makefile文件是通过工具生成的。makefile文件里面不用写头文件。为每个工程配上makefile文件,在编译时只需make指令就可以完成编译工作。

make指令会读取makefile文件中的内容,按照makefile文件编译代码。

(1)makefile文件的编写

通过vi makefile创建一个makefile文件:

在这里插入图片描述
在vi中编写makefile文件:

假设现在要生成最终的可执行文件main:

第一步:指定最终生成的可执行程序main

格式:

all:main

第二步:写可执行程序main的依赖文件和依赖文件的编译规则

格式:

main:main.o add.o max.o
	gcc -o main.o add.o max.o

编译main.o add.o max.o这三个文件时,gcc前面必须要输入tab键(缩进)。

第三步:写可执行文件main的main.o、add.o、max.o文件的依赖文件和依赖文件的编译规则

格式:

main.o:main.c
	gcc -c main.c
add.o:add.c
	gcc -c add.c
max.o:max.c
	gcc -c max.c

以上步三步总结起来就是all去指定最终生成的可执行程序为main程序,然后我们的程序就会去找main程序和它的依赖文件main.o、add.o、max.o,然后通过编译规则gcc -o main.o add.o max.o生成可执行程序main。如果没有找到main程序的依赖文件main.o、add.o、max.o,接着就会分别去找main.o、add.o、max.o的依赖文件main.c、add.c、max.c,找到之后通过编译规则gcc -c main.cgcc -c add.cgcc -c max.c将main.c、add.c、max.c文件分别转换成main.o、add.o、max.o文件,然后通过编译规则gcc -o main.o add.o max.o生成可执行程序main。

第四步:清理工程,把整个过程中不是自己写的代码,也就是中间生成的一些文件删掉。

格式:

clean: 
	rm -rf *.o main

-r是为了删除可能会生成的一些目录文件,-f是为了删除时忽略main没有生成的情况,在上面例子中所有的.o文件和main都是这个过程中生成的一些文件,所以要删掉。

具体如下图所示:

在这里插入图片描述

保存退出之后就可以使用make指令编译代码。

makefile文件中还可以写入安装指令install,但是安装指令需要在管理员模式下用make指令来实现。

(2)make指令编译代码并在编译完成后执行程序main

在这里插入图片描述

在make指令执行完之后可以通过make clean执行对应的规则,去删除.o文件和main程序:

在这里插入图片描述
①此时再去执行两次make指令:

在这里插入图片描述

出现这样的结果是因为我们并没有修改代码,所以不需要去编译,整个代码是最新的。

②如果修改add.c中的代码,在代码中加一个空格(在分号前面加一个空格)并保存,并没有改变代码的逻辑:

在这里插入图片描述

此时,通过make指令编译代码:

在这里插入图片描述
可以发现将add.c重新编译了,然后进行重新连接生成最终的main程序。

八、运行

通过路径运行可执行文件:
在这里插入图片描述

九、调试

在生成可执行程序后才能进行调试程序,调试程序主要是解决逻辑上的错误和软件上的权限。也就是编译成功才能进行调试,如果编译不成功就是存在语法问题。编译成功后运行的结果和我们期望的结果不一样的时候进行调试程序。

调试的对象:运行着的程序(进程)。不是调试main.c也不是调试main,而是调试正在运行着的main。

跟踪程序:gdb是跟踪程序的一个工具,只能跟踪含有调试信息的程序,也就是说只能跟踪debug版本不能跟踪release版本

1.Debug 版本和 Release 版本

(1)Debug 版本

Debug 版本为可调式版本,生成的可执行文件中包含调试需要的信息。我们作为开发人员,最常用的就是debug版本的可执行文件。

(2)Release 版本

Release 版本为发行版本,是提供给用户使用的版本。用gcc默认生成的就是Release版本,不包含调试信息。

首先将源代码编译、链接生成Debug版本的可执行文件,然后通过‘gdb Debug版本的可执行文件名’进入调试模式。

(3)Release 版本中生成调试信息

因为调试信息是在编译过程时加入到中间文件(.o)中的,所以必须在编译时控制其生成包含调试信息的中间文件。

生成调试调试信息:gcc -c main.c -g

在这里插入图片描述

可以看出在没有生成调试信息是可执行程序main的大小为16816,生成调试信息之后main的大小为19944,说明此时为调试版本。

生成包含调试信息的中间文件 :gcc -o hello hello.o 或者 gcc -o hello hello.c -g

(4)把调试版本容纳到makefile文件中

在这里插入图片描述

第8行gcc -o main main.o add.o max.o是一个链接过程,并不是编译过程,而调试信息是在编译过程生成的,所以gcc -o main main.o add.o max.o后面不能用写$(GDB)

此时,用make指令进行编译就是调试版本:

在这里插入图片描述
如果下次想用Release 版本,那就把makefile文件中的GDB=-g改为GDB= ,这时就从调试版本转换到了Release 版本。

猜你喜欢

转载自blog.csdn.net/NuYoaH502329/article/details/132238927
今日推荐