【项目一】GCC(gcc,g++)、静态库、动态库、MakeFile、GDB调试

news2024/11/26 21:38:10

GCC、静态库

    • 1.2 GCC(1)gcc
      • (1)常用命令
      • (2) C程序编译过程
      • (3)GCC工作流程
    • 1.3 GCC(2)g++
    • 1.3静态库的制作
    • 1.5静态库的使用
    • 1.6动态库的制作
    • 1.7动态库加载失败的原因
    • 1.8解决动态库加载失败的原因(用add把动态库加载到内存中去)
    • 1.9静态库与动态库对比
    • 1.10MakeFile
    • 1.13 GDB调试
      • 1.13.1 GDB准备、启动、退出、查看代码
      • 1.13.2 GDB断点操作
      • 1.13.3 GDB利用断点查看数值

1.2 GCC(1)gcc

在这里插入图片描述

(1)常用命令

1、ctrl+l 清空屏幕
2、使用gcc编译
gcc xx.c -o app
解释:gcc + 文件名 + -o(用于指定编译后的文件名) + app(文件名)
3、生成可执行文件
./app
解释:运行刚刚编译出来的文件
如果gcc xx.c -o app不加-o,只有gcc xx.c
那么会生成一个a.out的可执行程序

(2) C程序编译过程

在这里插入图片描述

高级语言 编译 成汇编语言
汇编语言 汇编 成机器语言
机器语言 运行

(3)GCC工作流程

在这里插入图片描述

预处理:
1、展开头文件,将头文件中的内容复制进源代码
2、删除注释
3、对定义的宏做宏替换
指令: gcc test.c -E -o test.i

编译器:
将源代码编译成汇编代码(.s)
gcc test.i -S -o test.s
直接执行gcc test.c -S也会生成.s文件(就包含了预处理这一步)

汇编器:
将汇编代码汇编成目标代码(.O)
gcc test.s -c -o test.o

链接:
-c 生成目标代码 test.o,test.o 不是一个可执行程序。如果下一步需要继续链接成可执行程序,需要输入指令 gcc test.o -o test.out(这里直接将 .o 目标文件链接成可执行程序 test.out,可以有多个 .o 文件,这里只有一个

所以整个直接 gcc test.c 包含了预处理,编译,汇编,链接成可执行文件4步。

1.3 GCC(2)g++

别管那么多,c就用gcc,cpp就应g++

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
-D使用示例:


#include <stdio.h>
#define PI 3.14

int main(){
    int a = 10;
#ifdef DEBUG
    printf("我不会爬树\n");
#endif // DEBUG
    for(int i = 0; i < 3; ++i){
        printf("hello,GCC\n");
    }
    return 0;
}   

在这里插入图片描述
-Wall使用示例:
在这里插入图片描述

在这里插入图片描述

1.3静态库的制作

在这里插入图片描述静态库实际上是将.c文件们打包。这些.c文件定义的函数,都在.h文件中申明。这样只需要把静态库和头文件给用户,用户就可以知道那些函数可以调用,但不清楚函数的具体实现。

-c使用示例:(生成.o文件)
在这里插入图片描述制作静态库之前,首先需要把.c文件用gcc命令和 -c选项做成.o文件。 src目录下:gcc -c add.c div.c mult.c sub.c 是要报错的,因为找不到.h文件。如下所示。
在这里插入图片描述所以实际上还要加上-I(大写i)选项,后面跟上.h所在的文件夹路径,告诉编译器去这个路径下找头文件:
gcc -c add.c div.c mult.c sub.c -I …/include/
注:.c文件在-c选项的前面还是后面无所谓
gcc add.c div.c mult.c sub.c -c -I …/include/
也可以。

ar命令的使用:(将.o文件打包成静态库)
ar rcs libsuanshi.a add.o div.o sub.o mult.o
移动命令:mv + 文件名 + 目的文件夹路径

1.5静态库的使用

在这里插入图片描述

参数选项
1、-I(大写i) :查找头文件的路径 (后面跟目录)
使用: -I 路径
例如:gcc main.c -o app -I ./include/
在这里插入图片描述此时只找到了头文件,但没找到这些函数的定义,也就是静态库

2、-l(小写L):指定加载哪个库(后面跟的是库名字,不是库的文件名)
文件名:libcala.a
库名:calc

3、-L:指定到哪个文件夹下去找静态库(后面跟目录)

示例:
gcc main.c -o app -I ./include/ -l calc -L ./lib/
在这里插入图片描述

1.6动态库的制作

在这里插入图片描述

什么叫:与位置无关?
“与位置无关”(Position-Independent Code,简称PIC)的代码是一种可执行代码,它在内存中的位置不影响其执行。换句话说,它可以在任何地方执行,而不需要修改。
这是通过使所有代码引用都通过间接寻址实现的,如通过全局偏移表(Global Offset Table,简称GOT)。例如,不是直接引用数据或函数的绝对地址,而是从GOT中查找这些地址。
这种方法的主要好处之一是,可以创建可以在多个程序之间共享的库。这就是所谓的动态链接库或共享库。因为每个程序可以将库加载到内存中的不同位置,而库代码的执行不受其在内存中的实际位置影响,因此可以共享。
如果你在用gcc编译代码时,可以使用-fPIC或-fpic选项来生成与位置无关的代码。这两个选项之间的区别在于,-fpic生成的代码使用的GOT较小,因此可能在大型程序中无法使用,而-fPIC则没有这个限制,但生成的代码可能会稍大一些。在大多数情况下,建议使用-fPIC选项。

1、制作动态库:
生成与位置无关的.o文件
gcc -c -fpic add.c div.c sub.c mult.c (如果头文件不在,记得指定头文件文件夹 -I …/include/ )
生成动态库
gcc -shared add.o sub.o mult.o div.o -o libcalc.so

2、使用动态库
在这里插入图片描述
与使用静态库一样,要指定头文件所在路径。动态库所在路径以及要使用的动态库名字(不是文件名字)
gcc main.c -o main -I ./include/ -l calc -L ./lib/

但这样使用会报错,运行main这个可执行文件的时候找不到动态库文件
在这里插入图片描述

1.7动态库加载失败的原因

原因:gcc在链接时动态库代码不会被打包进可执行文件中,只会放入一些相关信息。所以在程序运行以后,需要通过系统的动态载入器找到动态库的绝对路径(找的顺序如下图所示),然后把动态库加载到内存中。如果我们没给这个绝对路径,那就会找不到动态库。
在这里插入图片描述

ldd:list dynamic dependendcies 列出动态依赖库
在这里插入图片描述后面的一串数组是内存地址,此时可以看到 libcalc.so这个动态库没有被找到。

每个程序就是一个进程,linux会为每个进程分配虚拟地址空间(DT_RPATH段)

1.8解决动态库加载失败的原因(用add把动态库加载到内存中去)

1、配置环境变量
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/wcx/linux/lesson06/library/lib(冒号后面是动态库的绝对路径)
查看是否配置成功
1)echo $LD_LIBRARY_PATH
回车以后会显示绝对路径
在这里插入图片描述

2)ldd + 可执行文件
会列出该文件需要的动态库以及各个库的位置
在这里插入图片描述

弊端
在终端的环境变量里配置只是临时的,一旦开一个新终端就失效了

2、用户级别的配置
配置.bashrc文件,在home目录下(~)
vim打开
shift+G跳到最后一行
o 往下插入一行
输入配置路径:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/wcx/linux/lesson06/library/lib
esc退出编辑模式,shift+:后,wq保存并退出
配置完成后还需要使文件生效 . .bashrc。第一个点相当于source,所以写成 source .bashrc也可以

这样配置好的动态库可以直接运行可执行文件,不必再指定头文件和库文件的位置。

3、系统级别的配置
需要管理员权限
sudo
vim /etc/profile
到最后一行
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/wcx/linux/lesson06/library/lib
保存退出
配置完成后还需要使文件生效 . /etc/profile。第一个点相当于source,所以写成 source /etc/profile也可以

以上两种配置环境变量的方式打开新的终端可能还要source以下文件才能生效。同样,如果删除这条环境变量,需要开一个新终端才能生效。

4、配置 /etc/ld.so.cache文件
该文件是二进制文件,无法直接输入
所以要通过sudo vim /etc/ld.so.conf文件配置
进入文件后,将绝对路径复制进去就行/home/wcx/linux/lesson06/library/lib
更新:sudo ldconfig ( ldconfig第一个字母是小写L)

5、把文件放到 /lib/ 或者 /user/lib目录下
但是不建议,因为里面本身就包含了许多系统自带的库文件,如果自己写得库文件和系统重名,有可能会被替换,很危险。

1.9静态库与动态库对比

总得来说:库比较小就用静态库,比较大就用动态库
在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

发布程序无需提供静态库,移植方便
打包成可执行程序以后直接把可执行程序给别人就可以,不用给静态库,因为静态库已经复制进去了。

消耗系统资源,浪费内存
多个程序使用同一个静态库的时候,每一个程序都会把静态库复制进去

更新、部署、发布麻烦
由于每个程序之间相互独立,如果静态库做修改,那么所有涉及到这个静态库的程序都要重新编译

在这里插入图片描述

1.10MakeFile

在这里插入图片描述在这里插入图片描述1、创建MakeFile文件示例
以该文件夹下文件为例:
在这里插入图片描述1)vim Makefile 创建新文件并进入
2)编写Makefile
在这里插入图片描述3)执行make命令
会自动找到当前目录下的那个Makefile文件

在这里插入图片描述
命令在执行之前,需要先检查规则中的依赖是否存在
如果存在,执行命令
如果不存在,向下检查其它的规则,检查有没有一个规则是用来生成这个依赖的如果找到了,则执行该规则中的命令
在这里插入图片描述

比如这里第一条规则要找.o文件
不存咋,所以往下看其他规则,先把.c文件生成成.o文件
此外,由于MakeFile中其他规则都是为第一条规则服务的,如果与第一条规则无关,那就不会被执行。比如最后一行有个
b.o:b.c
gcc -c b.c -o b.o
跟第一行规则无关,就不会生成b.o文件

检测更新,在执行规则中的命令时,会比较目标和依赖文件的时间
如果依赖的时间比目标的时间晚,需要重新生成目标
如果依赖的时间比目标的时间早,目标不需要更新,对应规则中的命令不需要被执行

在这里插入图片描述在这里插入图片描述

在这里插入图片描述在这里插入图片描述

现在,在第一条规则中找依赖。发现4个.o文件都没有,于是会向下找规则来生成.o文件。四个.o文件其实用的规则是一样的,所以我们可以用模式匹配。首先找sub.o文件,发现下面有规则适用,于是调用。然后找add.o发现这个规则也适用,于是继续调用。

在这里插入图片描述

$(函数名 参数)
上图中,wildcard就是函数名 wildcard:未知数
示例中:.c ./sub/.c 是两个目录,意思是要获取当前目录下的所有.c文件,以及当前目录下的sub目录下,所有.c文件。多个目录之间用空格隔开

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

关于伪命令
clean:
rm &(objs) -f
这条规则其实不生成任何文件
但如果在当前目录下有了一个clean文件,在执行这条命令的时候就会比较依赖和目标的前后。由于没有依赖,目标就会是最新的,这个命令就会一直不执行。
所以要在前面加上 .PHONY,说明他后面跟的目标都被是伪目标。这样即使有clean文件也不影响这个命令的执行。
注:
在执行make的时候,由于clean和第一条规则无关,所以不会自动执行,要 make clean才会执行

1.13 GDB调试

在这里插入图片描述

在这里插入图片描述在这里插入图片描述

1.13.1 GDB准备、启动、退出、查看代码

1、准备工作:使用-g选项生成带源码信息的可执行程序
在这里插入图片描述可以看到,test文件大于test1文件,说明-g选项添加一些源码信息到可执行文件中。
注:-h选项是在列出文件信息的时候,把文件大小转成更容易阅读的K,KB ,G等大小

2、启动调试
gdb+可执行程序
在这里插入图片描述
3、给程序设定参数
test.c文件中可以看到,main函数是有参数的
在这里插入图片描述
设置参数:set args +参数

显示参数:show args
在下一行就会有:程序开始调试时的参数列表是:10 20在这里插入图片描述4、退出gdb调试模式
直接写quit或者q就可以
在这里插入图片描述5、help
在调试模式下,键入help,help all是显示所有帮助信息,可以回车显示下一屏。
如果需要有针对显示 可以写 help set
那么就会显示所有set开头的命令,比如 set args

5、查看代码
vim test.c
set nu 显示行号
也可以在gdb里面查看
1)list就可以,一次显示10行,回车或者list显示下面10行
2)list + 行号:list 20 就会把20作为中间行,显示15-25行
3)list+函数名:list main 会把main函数开始的那一行作为中间行显示出来
4)有时候可执行文件不会只有一个.c文件生成
在这里插入图片描述
此时直接输入list或者l,默认显示main函数所在的文件
如果查看非当前文件代码:
list/1 文件名:行号:list bubble.cpp:1
list/1 文件名:函数名:list select.cpp:selectSort

6、设置显示的行数
show list/listaize
set list/lintaize 行数
在这里插入图片描述

1.13.2 GDB断点操作

在这里插入图片描述在这里插入图片描述

在设置断点的时候,和list一样,如果不指定文件,断点就打在main函数所在的文件里

删除断点

在这里插入图片描述使断点无效

在这里插入图片描述

设置条件断点

在这里插入图片描述

只有当i=3时,才会在16行停住。

1.13.3 GDB利用断点查看数值

在这里插入图片描述
1、运行GDB程序
start:程序停在第一行
run(遇到断点才停)
2、继续运行,到下一个断点停
c/continue
要是接下来没有断点,就会到程序结尾

在这里插入图片描述

在这里插入图片描述
打一些断点:

在这里插入图片描述

在这里插入图片描述

run 跑到第一个断点处
c 继续跑直到下一个断点。断点2是bubble文件的bublesort函数,所以会落到这个函数内的第一行,也就是for。list以下就能看到这个文件的第八行确实是函数内的第一行for
在这里插入图片描述

第三个断点在main的16行,是在一个for循环内
在这里插入图片描述
在这里插入图片描述

打印变量名
第一次打印i是2,continue(c),跑到下一个断点(因为在for循环内所以又到16行),此时再打印i是3.
在这里插入图片描述
打印变量类型
在这里插入图片描述

跳出循环
1、循环内不能有断点。
2、执行until,此时程序会一直执行,直到不再能够进入函数体
3、要连续两次until。并且循环内至少执行一次才能跳出循环
在这里插入图片描述
在这里插入图片描述
一开始 i = 2时,执行until,就会一直跑到 i = len。此时再执行step,就会到cout<<endl

next与step的区别
next遇到函数不会进入
在这里插入图片描述
step碰到函数会进入
在这里插入图片描述
注意:
如果想用finish跳出函数,函数体内不能有断点

自动变量操作
用test做测试
在这里插入图片描述
在这里插入图片描述
如果想查看a和b的值,每一次都print的话太麻烦,就可以设置的自动变量
display a
这样接下来每操作一次,都会自动输出a的值
在这里插入图片描述
还可以查看设置了哪些自动变量:info display
如果想取消自动变量:undisplay 编号 就行

设置变量值 set var
在这里插入图片描述
这里i走到3,如果想从i = 9开始走
就可以set var i= 9

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/627315.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

秋招必看,Java后端高频面试题1000题、拒绝简单背诵,深入浅出近30个技术栈

Java 面试随着时间的改变而改变。在过去的日子里&#xff0c;当你知道 String 和 StringBuilder 的区别就能让你直接进入第二轮面试&#xff0c;但是现在问题变得越来越高级&#xff0c;面试官问的问题也更深入。 在我初入职场的时候&#xff0c;类似于 Vector 与 Array 的区别…

面试专题:计算机网络常见面试点总结

socket、tcp、udp、http 的认识及区别 socket、tcp、udp、http 的认识及区别​ 一、先来一个讲TCP、UDP和HTTP关系的 1、TCP/IP是个协议组&#xff0c;可分为三个层次&#xff1a;网络层、传输层和应用层。 在网络层有IP协议、ICMP协议、ARP协议、RARP协议和BOOTP协议。 在传…

10分钟让你彻底了解Loadrunner性能测试工具

目录 Loadrunner简介 Loadrunner原理 Loadrunner工具组件 1、VUGen&#xff08;虚拟用户生成器&#xff09; 2、Controller&#xff08;控制器&#xff09; 3、Load Generator&#xff08;负载生成器&#xff09; 4、Analysis分析器 性能测试工具&#xff0c;从广义上讲…

Shell脚本攻略:Linux防火墙

目录 一、理论 1.安全技术 2.防火墙 3.通信五元素和四元素 二、实验 1.iptables基本操作 2.扩展匹配 一、理论 1.安全技术 &#xff08;1&#xff09;安全技术 ①入侵检测系统&#xff08;Intrusion Detection Systems&#xff09;&#xff1a;特点是不阻断任何网络访…

游戏外包开发技术难点分析

游戏开发涉及多个领域的技术&#xff0c;因此在开发过程中可能会遇到很多技术难点。今天和大家分享一些常见的游戏开发技术难点&#xff0c;希望对大家开发游戏有一定帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 1. 图形渲染…

「料见」vol25.回顾 | PKU-Beaver开源项目团队:一起来聊首个可复现的RLHF基准

为了解决复现RLHF技术和基于RLHF技术的大预言模型的不安全问题&#xff0c;北京大学团队开源了名为PKU-Beaver&#xff08;海狸&#xff09;开源项目。 第25期料见闭门分享会&#xff0c;我“门”非常开心邀请到PKU-Beaver开源项目团队成员——北京大学人工智能研究院助理教授…

欧美同学会第三届“双创”大赛——空天装备产业赛区(浙江诸暨)正式启动,开启报名通道

6月8日&#xff0c;欧美同学会第三届“双创”大赛——空天装备产业赛区&#xff08;浙江诸暨&#xff09;启动仪式暨北京推介会圆满举行。活动由欧美同学会&#xff08;中国留学人员联谊会&#xff09;主办&#xff0c;中共浙江省委统战部支持&#xff0c;浙江省欧美同学会、中…

国内比较火的报表工具测评——Smartbi电子表格软件和Finereport

最近在学习BI软件&#xff0c;因为最近工作中需要开发报表&#xff0c;因此选用了国内市场比较热门的报表工具——Finereport和Spreadsheet进行学习。 BI软件经常会定期发布新的版本&#xff0c;增加新的功能模块&#xff0c;或者对现有功能进行增强&#xff0c;提升运行效率。…

解决pip install -r requirements.txt 超时

解决方案&#xff1a; pip install -r requirements.txt -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com测试验证

让你的AndroidUI更亮眼:Jetpack Compose中的可视状态

让你的Android UI更亮眼&#xff1a;Jetpack Compose中的可视状态 任何设计系统的重要责任是清晰地表明哪些组件可以与之交互&#xff0c;哪些不行&#xff0c;并让用户知道交互已发生。本博客文章将解释如何监听Jetpack Compose中的用户交互&#xff0c;并创建可重用的视觉指…

关于接口的安全性测试,这几点你必须掌握!

01、接口防刷 1.为什么会有人要刷接口&#xff1f; 牟利&#xff1a;黄牛在 12306 网上抢票再倒卖。 恶意攻击竞争对手&#xff1a;如短信接口被请求一次&#xff0c;会触发几分钱的运营商费用&#xff0c;当量级大了也很可观。 压测&#xff1a;用apache bench 做压力测试。…

高性能计算与AI融合成为刚需|什么是高性能计算?应用领域有哪些?与人工智能的关系梳理

本文一部分转载自杨净 整理自 MEET2023量子位 算力的需求&#xff0c;远比以往来得更为猛烈。甚至有人直呼&#xff1a;得算力者得未来。 元宇宙、AIGC、AI for Science的涌现&#xff0c;又给高性能计算&#xff08;HPC&#xff09;平添了好几把火。 在诸多挑战与机遇共存交…

大数据治理入门系列:数据管理

在如今的大数据时代&#xff0c;每天都会产生大量的新数据&#xff0c;已有数据可能也会频繁更新或转换。因此&#xff0c;需要对数据进行治理和管理&#xff0c;以便高效地开展数据分析、获取数据洞见、挖掘数据价值。否则&#xff0c;杂乱无章的数据只会白白浪费存储空间&…

python基础----10-----python操作mysql

一 前言 对于SQL章节前言->SQL_DQL_排序分页的课程&#xff0c;这里不做记录&#xff0c;因为都是讲MYSQL本身的内容&#xff0c;与python无关。 当然&#xff0c;接下来的课需要用到mysql&#xff0c;所以大家需要自行下载&#xff0c;这并不难。 二 python操作MYSQL基础…

当BPM遇上低代码 “自定义”提升业务管理效率

业务流程管理&#xff08;BPM&#xff09;的历史可以追溯到科学管理和质量管理的发展&#xff0c;并逐步演变为一个更加系统化和综合的管理方法。它在现代组织中起到了优化业务流程、提高效率和质量、增强灵活性和创新能力的重要作用。 从20世纪初的科学管理理论中&#xff0c…

【Linux】什么是进程(process)?

目录 进程与程序概念描述进程-PCBWindows进程与Linux进程Linux进程操作子进程父进程创建进程(初识-fork) 进程与程序概念 在Linux系统中&#xff0c;触发任何一个事件时&#xff0c;系统都会将它定义成为一个进程&#xff0c;并且给予这个进程一个ID&#xff0c;成为PID&#x…

Apikit 自学日记:如何安装 Apikit

Apikit 有三种客户端&#xff0c;你可以依据自己的情况选择。三种客户端的数据是共用的&#xff0c;因此你可以随时切换不同的客户端。 肯定会有和我一样的小白&#xff0c;第一次听说 Apikit这个工具&#xff0c;那么我今天和大家一起学习下这个工具如何安装。 我们推荐使用新…

校招失败后,在小公司熬了 2 年终于进了华为,这次真是竭尽全力了····

其实两年前校招的时候就往华为投了一次简历&#xff0c;结果很明显凉了&#xff0c;随后这个理想就被暂时放下了&#xff0c;但是这个种子一直埋在心里这两年除了工作以外&#xff0c;也会坚持写博客&#xff0c;也因此结识了很多优秀的小伙伴&#xff0c;从他们身上学到了特别…

Angular实现用ng-class和ng-style控制数组最后一个数据为红色

首先我们来看class方案实现 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title>…

Python模块的安装

1.用pip命令安装模块 pip是python官方的编程环境提供的一个命令&#xff0c;主要功能就是安装和卸载第三方模块。 用pip命令安装模块的方法最简单也最常用&#xff0c;这种默认将模块安装在python安装目录中的“site-packages"文件下。 1.1 pip命令安装模块的具体方法 …