首页 > 其他分享 >GDB及Makefile学习

GDB及Makefile学习

时间:2022-10-05 15:55:42浏览次数:103  
标签:文件 bar int Makefile tool makefile 学习 GDB main

GDB

(1)下载安装gdb: sudo apt-get install gdb
(2)启动gdb gdb test

(3)启动后界面如下:
参考老师所给ppt内容

我们可以输入(gdb) l列出文件的代码清单

·(gdb) b
1.函数断点:在进入指定函数时停住。
2.行断点:在指定行号停住。eg: (gdb) b 8
3.条件断点:break ... if
4.临时断点:tb 行号

**·(gdb) r **运行被调试的程序。如果此前没有下过断点,则执行完整个程序;如果有断点,则程序暂停在第一个可用断点处。

**·(gdb) p i **显示指定变量(临时变量或全局变量)的值 ,这里就是打印输出变量i的值

·(gdb) finish 使一个函数结束

**·(gdb) q **退出断点调试

Makefile

什么是makefile?

makefile关系到了整个工程的编译规则。一个工程中的源文件不计其数,并且按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个 Shell脚本一样,其中也可以执行操作系统的命令。
makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。

compile和link(链接)的概念

源码compile(检查语法,有函数声明即可通过)后得到中间文件(UNIX是.o);
对中间文件进行打包得到库文件(UNIX是.a);
把它们link(将xx.o和xx.a合成一坨一个可执行文件)——链接函数和全局变量等,找不到函数实现就会出现link error——得到可执行文件UNIX无后缀

makefile和shell的区别

作用:
·shell是为了重用terminal内的命令服务的,是系统程序员与OS内核的交互接口;
·makefile是用于工程compile/link用的;
·makefile内可写shell命令、调用shell脚本,如:+ ./xxx.sh;
·shell内 =号不允许有空格,makefile内 =号空格无碍;
·shell内开头要写 #!/bin/bash,后缀名是.sh;
·shell内是自上而下执行,有数组、循环等;makefile内执行shell命令是一行独立一个进程,若想一个进程统一执行,得在末尾用 \ 表同一行。
·shell内通配符:*;makefile内通配符:%;
·shell内变量用 {},命令串用 ();makefile中访问变量用 $() 或 ${} 都行;
编写格式:

目标target:   所需prerequisites
(TAB) command (任意的Shell命令)
	
label:
(TAB) command...

makefile简单示例

示例①:我们创建一个project文件夹,在里边新建一个简单的test.c工程:

#include <stdio.h>
int main()
{
    printf("hello world\n");
    return 0;
}

根据我们上文列出的makefile编写规则

target: dependencies****
	command

我们编写以下makefile文件
先用vim makefile 创建一个makefile文件,文件内写入如下内容:

test: test.c
	gcc test.c -o test

发现运行成功

事例②:
我们创建以下几个文件:
main.c:

#include "tool.h"
#include "bar.h"
#include <stdio.h>
int main()
{
	int arr[5] = {1,9,3,8,0};
	int min = find_min(arr, 5);
	int max = find_max(arr, 5);
	printf("min = %d\n", min);
	printf("max = %d\n", max);
	return 0;	
}

tool.h:
int find_max(int arr[], int n);

tool.c:

#include "tool.h"
int find_max(int arr[], int n)
{
	int m = arr[0];
	for(int i = 0; i < n; i++)
	{
		if(arr[i] > m)
		{
			m = arr[i];
		}
	}
	return m;
}

bar.h:
int find_min(int arr[], int n);

bar.c:

#include "bar.h"
int find_min(int arr[], int n)
{
	int m = arr[0];
	for(int i = 0; i < n; i++)
	{	
		if(arr[i] < m)
		{
			m = arr[i];
		}
	}
	return m;
}
第一阶段makefile

编写makefile:

main: main.c tool.o bar.o
	gcc main.c tool.o bar.o -o main

tool.o: tool.c
	gcc -c tool.c

bar.o: bar.c
	gcc -c bar.c

clean:
	rm *.o main

首先,要从最终生成的可执行文件写起,此处为 main。还是先写
target - main,dependencies - main.c tool.o bar.o,
换行之后按下 tab 键,再写 command - gcc main.c tool.o bar.o -o main
然后,开始写依赖项 tool.o bar.o
依赖中间文件 .o 文件生成最终的可执行文件,可以避免编译整个文件。哪个文件发生了改变,只需编译该文件对应的 .o 文件即可。之后再与其他文件共同生成最终的可执行文件。

从图中可以看出,terminal 中的执行顺序是与 Makefile 中的书写顺序相反的,将 Makefile 中的内容由下至上执行

第二、三阶段makefile

makefile变量
使用OBJ变量、省去指令内容,自动推导:

这种自动推导过程叫做隐含规则
“隐含规则”也就是一种惯例,make会按照这种“惯例”心照不喧地来运行,那怕我们的Makefile中没有书写这样的规则。例如,把[.c]文件编译成[.o]文件这一规则,你根本就不用写出来,make会自动推导出这种规则,并生成我们需要的[.o]文件。

第四阶段makefile

自动变量($^ $< $@)
具体意义如下:
$@ :指代当前规则下的目标文件列表
$< :指代依赖文件列表中的第一个依赖文件
$^ : 指代依赖文件列表中所有依赖文件
$? : 指代依赖文件列表中新于对应目标文件的文件列表

多个文件makefile的编译

如果有多个文件,这时候不能并列写编译,而是要在开头添加all声明
依旧拿我们刚才的例子,这次我们在两个目标程序前添加一个all,随后编译运行,成功~
makefile:

all:main_max main_min
main_max: main_max.c tool.o bar.o
	gcc main_max.c tool.o bar.o -o main_max
main_min: main_min.c tool.o bar.o
	gcc main_min.c tool.o bar.o -o main_min
tool.o: tool.c
	gcc -c tool.c
bar.o: bar.c
	gcc -c bar.c
clean:
	rm *.o main_max main_min

makefile的工作原理

目标的生成: a. 检查规则中的依赖文件是否存在; b. 若依赖文件不存在,则寻找是否有规则用来生成该依赖文件

比如上图中,生成calculator的规则是gcc main.o add.o sub.o mul.o div.o -o,Makefil会先检查main.o, add.o, sub.o, mul.o, div.o是否存在,如果不存在,就会再寻找是否有规则可以生成该依赖文件。

比如缺少了main.o这个依赖,Makefile就会在下面寻找是否有规则生成main.o。当它发现gcc main.c -o main.o这条规则可以生成main.o时,它就利用此规则生成main.o,然后再生成终极目标calculator。
目标的更新: a. 检查目标的所有依赖,任何一个依赖有更新时,就重新生成目标; b. 目标文件比依赖文件时间晚,则需要更新。

参考博客:
[https://blog.csdn.net/weixin_44498318/article/details/115769976?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-8-115769976-blog-125890413.pc_relevant_multi_platform_whitelistv3&spm=1001.2101.3001.4242.5&utm_relevant_index=11](Linux Makefile快速入门)
https://blog.csdn.net/qq_34623621/article/details/121537317

标签:文件,bar,int,Makefile,tool,makefile,学习,GDB,main
From: https://www.cnblogs.com/ssssspm/p/16754077.html

相关文章

  • Empire Breakout学习体会
    申明:本文为靶机EMPIRE:BREAKOUT学习笔记,相关操作仅在测试环境中进行,严禁任何危害网络安全的恶意行为。本文主要记录了一些关键知识点,仅供学习!一、安装说明靶机在https://ww......
  • 机器学习实战-朴素贝叶斯
    1.优缺点优点:在数据较少的情况下仍然有效,可以处理多类别问题。缺点:对于输入数据的准备方式较为敏感。适用数据类型:标称型数据2.朴素贝叶斯的一般过......
  • 深度学习pytorch之线性回归实现
    importtorchfrommatplotlibimportpyplotasplt#损失率:learn_rate=0.1#训练数据x=torch.rand([500,1])y=3*x+0.8#参数w=torch.rand([1,1],req......
  • MYSQL学习之视图
    (一)什么是视图??  视图就是站在不同的角度取看待同一份数据。(二)基本操作表复制:mysql>createtabledept2asselect*fromdept;#复制mysql>createtablescholar1assel......
  • 论文翻译 | LS-Net:单目双目视觉的非线性最小二乘学习算法
    1摘要在本文中,我们提出了最小二乘网络,一种神经非线性最小二乘优化算法,即使在逆境中也能有效地优化这些代价函数.与传统方法不同,所提出的求解器不需要hand-crafted的正则......
  • Rust学习 - Sized trait
    Sizedtrait的作用是什么?编译期用它来识别在编译期确定大小的类型。Sizedtrait是空trait,仅仅作为标签trait供编译期使用。真正起“打标签”作用的是属性#[lang="s......
  • C语言学习记录3
    #每日美图分享##include<stdio.h>intmain(){inti=1;while(i<=10){if(i==5)continue;printf("%d\n",i);i++;}return0;}该代码的运行结果为:1234而......
  • go学习
    一、接口定义概念:Interface类型可以定义一组方法,不需要实现,并且不能包含任何变量,称之为接口。接口不需要显式的实现,只需要一个变量,含有接口类型中的所有方法,那......
  • STL学习笔记
    目录STL介绍什么是STL泛性编程STL基本组成STL序列式容器什么是STL容器什么是迭代器什么是序列式容器array容器vector容器deque容器list容器STL关联式容器pair容器map容器mu......
  • 学习Python,一路绕来绕去推荐给你的教程!
         说实话,学习一门语言不难。但是,但是能用该语言编写程序做项目,又是另外一回事。一路走来,java,Android,go,c#,c,ASM,c++,pascal,Basic,foxpro,QT,HTML,Rust,Python,Ruby,JS,PHP等......