3

Linux学习笔记(4)

 2 years ago
source link: https://blog.csdn.net/m0_53005929/article/details/122401045
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

🍅Linux编译器gcc与g++🍅

我们习惯用gcc 编译C语言代码,g++编译C++的代码

gcc也可以编译Go语言程序之类的,gcc可以根据文件后缀来判断当前程序所用的语言

以test.c为例:

gcc -E test.c -o test.i 预处理:完成宏替换,去掉注释,头文件包含等工作

gcc -S test.i -o test.s 编译: 把C语言代码转化成汇编语言的代码

gcc -c test.s -o test.o 汇编:把汇编语言的代码转成机器语言(二进制序列)

gcc test.o -o mytest 链接:生成可执行程序(默认是动态链接)

🍅gcc演示🍅

下面对每步进行演示

📖①**vim test.c**

在这里插入图片描述

📖②gcc -E test.c -o test.i

-E 作用:预处理,但不生成文件

-o的作用:把生成的内容输出到文件,此外有给文件起名的作用

gcc -E test.c -o test.i 里的-o就是把预处理的内容输出到test.i里,不然直接打印到屏幕上了

cat -n test.i

test.i的内容

在这里插入图片描述

📖③gcc -S test.i -o test.s

-S:编译 ,不生成文件

-o 把生成的内容放入test.s

cat -n test.s

生成的汇编代码如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9bUigwPn-1641739327072)(../typora 图片/image-20220109164421642.png)]

📖④gcc -c test.s -o test.o

-c 汇编不生成文件

-o 把生成的内容放入test.o

cat -n test.o

看不懂对吧,我也看不懂,可以转为二进制文件看

xxd test.o

在这里插入图片描述

看不懂对吧 我也看不懂🐱‍🏍

📖⑤gcc test.o -o mytest

这一步写成 gcc test.o -o mytest.exe 效果一样,Linux不是根据扩展名来给文件归类的,反正都是可执行文件,具有x权限

gcc test.o :链接 生成可执行文件.

mytest文件就不看了,和上面的test.o差不多,也是二进制文件

链接分为动态链接和静态链接,默认是动态链接

ldd和file可以判断链接类型

📖 ldd mytest

在这里插入图片描述

.so可以判断动态链接,.a判断是静态链接

libc.so.6就是个动态库,libc.a就表示是个静态库

在这里插入图片描述

📖file mytest

📖 英文时间:dynamically linked==动态链接
在这里插入图片描述

既然有动态链接 肯定就有静态链接 两者区别又是什么?

动态链接用到的是静态库,运行时加载库。

静态链接则是直接包含库,所以静态链接生成的文件会很大

怎么生成静态链接的可执行文件?

加-static

举例:gcc test.c -o mytest-s -static(如果报错了拉到下一个块解决报错)

生成的mytest-s就是静态链接的,看看具体信息

file mytest-s

在这里插入图片描述

📖 英文时间:statically linked==静态链接

📖 再比较下动态和静态库的大小

在这里插入图片描述

静态链接生成的文件大小是动态链接生成的100倍左右

不过静态链接也有优点,没有那么依赖配置环境,拿过来就能用。

不加-static默认是动态链接

🍅解决static报错问题🍅

报错信息:

/usr/bin/ld: cannot find -lc
collect2: error: ld returned 1 exit status

原因:少了静态库…搞了半天才解决

解决: sudo yum install glibc-static

把库给装上就完事了

补充:gcc -w 不生成任何警告

gcc -Wall 生成所有警告

我们默认是报警告的,所有默认是gcc -Wall

test.cpp test.cc test.cxx都表示c++文件

gcc编译器可以根据文件后缀判断文件的编程语言
英文时间: pwd==print work directory

🍅gdb的使用🍅

什么是gdb?

简单来说就是调试器,比如vs里的调试器

gdb 可执行程序

作用:进入调试

如gdb mytest

**如果报错:**重新生成可执行文件,gcc命令加上-g,不加默认release版本

gcc mytest -g

报错原因:文件里没有调试信息,也就是我们常说的release版本

gdb界面输入命令报错信息:No symbol table is loaded. Use the “file” command.

-g可加入调试信息 ,release版本无调试信息,不可被调试

检查当前文件是否具有调试信息

readelf -S mytest |grep debug

效果如图:(不打印则说明没有debug信息)
在这里插入图片描述

📖 小知识:为什么会有debug和release?

debug是给我们开发时用的,release一般是给用户用的

调试信息也占空间啊

如果只有debug版本,用户又不用调试,调试信息又多占了程序空间

所以对用户来说对debug的需求不强(没有)

如果只有release版本,自己感受一下出了bug没有调试器的感觉[doge]

📖 quit(q)或者ctrl+d:退出gdb

l :显示十行代码 按回车显示十行后的代码

但不一定是开头十行

📖 list (l) 行号:显示行号所在的代码

📖 l 函数名 :显示函数的代码

📖 b 行号:给某行加断点 (b== Breakpoint )

如 b 7

📖 b 函数名:在函数入口加断点

📖 info b:列出所有断点

📖 r :开始调试 两次r重新调试 r ==run

📖 n : 逐过程(不会进入函数) n ==next

📖 p 变量:打印变量的值,但只显示一次

📖 print 表达式:打印表达式的值(变量也算入表达式)

📖 display 变量:长显示,每次n都会打印

​ 比如display sum 长显示sum,每次n都会显示sum的值

📖 undisplay 编号 取消长显示 注意是编号不是变量名

在这里插入图片描述

📖 c (continue): 跳到下一个断点

📖 d 编号 :删除断点

在这里插入图片描述

📖 s 逐语句 :会进入函数

📖 bt :显示调用堆栈

📖 until 行号 跳转到函数里的任意位置

和断点有一些冲突

for( i=0;i<=top;i++)
{
(断点)	 sum+=i;//断点启用时(走到这行了用until) until未能跳出循环
}

📖 finish 跑完当前函数 (官方点:执行到当前函数返回,然后停下来等待命令 非main函数)

在这里插入图片描述

📖 c until finish :跳转三剑客了属于是 🗡

Enb=enable y表示断点可用
在这里插入图片描述

📖 disable 断点编号 :禁用断点

为啥要禁用断点呢,我不用直接删掉不就行了

答:保留调试痕迹,方便多次调试

📖 delete breakpoint 、delete breakpoints :删掉全部断点

set var 变量:改变调试时变量的值

比如set var i=100,用的比较少

注:改变变量的值不是VS里的条件断点,而是直接改变往后运行

🍅Linux项目自动化构建工具 -make/Makefile🍅

make:这是一条指令

makefile/Makefile:这是一个文件

gcc test.c -o test.exe
test.c
test.exe

test.exe的生成依赖于test.c

📖 touch makefile/touch Makefile

makefile里面写的是依赖关系和相应的操作

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

mytest:test.o 表示mytest依赖于test.o生成,表现出依赖关系
gcc test.o -o mytest gcc前面必须是Tab 不能是四个空格
test.o:test.s 表示test.o依赖于test.s生成,表现出依赖关系
gcc -c test.s -o test.o
test.s:test.i 表示test.s依赖于test.i生成,表现出依赖关系
gcc -S test.i -o test.s
test.i:test.c 表示test.i依赖于test.c生成,表现出依赖关系
gcc -E test.c -o test.i

📖 解释一下这个make吧 ,相当于一次性执行了多条命令,降低了我们的调试的成本

如果文件很多 写gcc一个一个编译链接过去成本太高

或者是软件迭代的时候,进行测试等操作时一个一个写gcc成本太高了

项目管理有生成文件的,自然就有删除文件的

📖 删除文件时makefile这么写:

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

📖 .PHONY:clean又是什么东西???

.PHONY很像一个声明,声明一下clean,或者说修饰一下clean

.PHONY定义伪目标,被修饰的clean总是被执行

⌨ 总是被执行?那肯定就有总是不被执行了

默认:总是不被执行

下面的make就是总是不被执行,即只能被执行一次,也一直提示make: `mytest’ is up to date.

同时对比clean
在这里插入图片描述

看到这还有一个问题

📖 为什么生成文件时只需要输入“make”而我在删除文件时却要输入“make clean”?

因为make就是从makefile文件由上往下走,执行第一条命令

这么说很晦涩,举个例子
在这里插入图片描述

全称就应该写 make mytest,只不过mytest相关命令写在clean前面,所以可以简写为make

如果把clean写在第一行,那make命令执行的就是删除功能了,有兴趣可以试试
此外make命令不会检查文件是否存在,找不到操作的文件就直接报错退出了

🍅简写makefile文件🍅

  1 mytest:test.o
  2   gcc $^ -o $@      $@依赖于$^,类似于代指
  3 test.o:test.s
  4   gcc -c $^ -o $@
  5 test.s:test.i
  6   gcc -S $^ -o $@
  7 test.i:test.c
  8   gcc -E $^ -o $@

在这里插入图片描述

如果有帮助的话麻烦点个赞鼓励一下!

4aec5ca1d277486581beaad286b07c54.png

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK