文章目录

  • 前言
  • 一.编辑器gedit介绍
  • 二.什么是vi(vim)
  • 三. vim工作模式
    • 1. 命令模式
    • 2. 编辑模式
    • 3 .末行模式
  • 四. vim教程
  • 五. vim基本操作
  • 六. vim实用操作
    • 1. 命令模式下的操作
    • 2. 末行模式下的操作
  • 七. GCC编译器简介
  • 八. GCC工作流程和常用选项
  • 九. 静态库和动态库简介
  • 十. 静态连接和动态连接
  • 十一. 静态库制作和使用
  • 十二.动态库制作和使用
  • 十三. GDB调试器
    • 1. GDB简介
    • 2. 生成调试信息
    • 3. 启动GDB
    • 4. 显示源代码
    • 5. 断点操作
    • 6. 条件断点
    • 7. 维护断点
    • 8. 调试代码
    • 9. 自动显示
    • 10. 查看修改变量的值
    • 11. 数据查看
  • 扩展
    • 一.静态链接库、动态链接库(C/C++)

前言

此篇内容全是知识点,可用作帮助手册,一些晦涩难懂的我已测试教程及运行截图;注意:那些没实现的不是不重要,而是需要自己动手实践一遍,不然纯理解,隔天就忘.

一.编辑器gedit介绍

gedit是一个GNOME桌面环境下兼容UTF-8的文本编辑器。它使用GTK+编写而成,因此它十分的简单易用,有良好的语法高亮,对中文支持很好,支持包括gb2312、gbk在内的多种字符编码。gedit是一个自由软件。

这是 Linux 下的一个纯文本编辑器,但你也可以把它用来当成是一个集成开发环境 (IDE), 它会根据不同的语言高亮显现关键字和标识符。

gedit是一个Linux环境下的文本编辑器,类似windows下的写字板程序,在不需要特别复杂的编程环境下,作为基本的文本编辑器比较合适。

xcc@machine:~$ gedit txt &

打开gedit图形界面如下:

二.什么是vi(vim)

vi (Visual interface)编辑器是 Linux 系统中最常用的文本编辑器,vi 在Linux界有编辑器之神的美誉,几乎所有的 Linux 发行版中都包含 vi 程序。

vi 工作在字符模式下,不需要图形界面,非常适合远程及嵌入式工作,是效率很高的文本编辑器,尽管在 Linux 上也有很多图形界面的编辑器可用,但vi的功能是那些图形编辑器所无法比拟的。

vim 是 vi 的升级版,它不仅兼容 vi 的所有指令,而且还有一些新的特性,例如 vim 可以撤消无限次、支持关键词自动完成、可以用不同的颜色来高亮你的代码。vim 普遍被推崇为类 vi 编辑器中最好的一个。

vim键盘

三. vim工作模式

vi有三种基本工作模式: 命令模式、文本输入模式(编辑模式)、末行模式

1. 命令模式

任何时候,不管用户处于何种模式,只要按一下ESC键,即可使vi进入命令模式。我们在shell环境(提示符为$)下输入启动vim命令,进入编辑器时,也是处于该模式下。

在命令模式下,用户可以输入各种合法的vi命令,用于管理自己的文档。此时从键盘上输入的任何字符都被当做编辑命令来解释,若输入的字符是合法的vi命令,则vi在接受用户命令之后完成相应的动作。但需注意的是,所输入的命令并不在屏幕上显示出来。若输入的字符不是vi的合法命令,vi会响铃报警。

2. 编辑模式

在命令模式下输入插入命令i(I)、附加命令a(A) 、打开命令o(O)、替换命s(S)都可以进入文本输入模式,此时vi窗口的最后一行会显示“插入”。

在该模式下,用户输入的任何字符都被vi当做文件内容保存起来,并将其显示在屏幕上。在文本输入过程中,若想回到命令模式下,按键ESC即可。

3 .末行模式

末行模式下,用户可以对文件进行一些附加处理。尽管命令模式下的命令可以完成很多功能,但要执行一些如字符串查找、替换、显示行号等操作还是必须要进入末行模式的。

在命令模式下,输入冒号即可进入末行模式。此时vi窗口的状态行会显示出冒号,等待用户输入命令。用户输入完成后,按回车执行,之后vi编辑器又自动返回到命令模式下。

四. vim教程

xcc@machine:~/test$ vimtutor

五. vim基本操作

6.1 打开文件

vim filename:打开或新建文件,并将光标置于第一行行首,如果文件不存在,则会新建文件。

打开不存在文件:

6.2 编辑文件

如果通过vi打开一个已经存在的文件,首先进入命令模式,此时输入的任何字符都被视为命令,不能输入内容。

在命令模式输入i

6.3 保存文件

一定要先退出插入模式(按Esc进入命令模式),然后(小写状态下),shift + zz (按住 “shift” + 按两下“z”键),或者(大写状态下:ZZ) 即可保存退出当前文件。

第一步:进入命令模式(ESC)

第二步:shifit + z z

六. vim实用操作

1. 命令模式下的操作

1)切换到编辑模式

按键 功能
i 光标位置当前处插入文字
I 光标所在行首插入文字
o(字母) 光标下一行插入文字(新行)
O(字母) 光标上一行插入文字(新行)
a 光标位置右边插入文字
A 光标所在行尾插入文字
s 删除光标后边的字符,从光标当前位置插入
S 删除光标所在当前行,从行首插入

2) 光标移动

按键 功能
Ctrl + f 向前滚动一个屏幕
Ctrl + b 向后滚动一个屏幕
gg 到文件第一行行首
G(大写) 到文件最后一行行首,G必须为大写
mG或mgg 到指定行,m为目标行数
0(数字) 光标移到到行首(第一个字符位置)
$ 光标移到到行尾
l(小写L) 向右移动光标
h 向左移动光标
k 向上移动光标
j 向下移动光标
^ 光标移到到行首(第一个有效字符位置)

3)复制粘贴

按键 功能
[n]yy 复制从当前行开始的 n 行
p 把粘贴板上的内容插入到当前行

4)删除

按键 功能
[n]x 删除光标后 n 个字符
[n]X 删除光标前 n 个字符
D 删除光标所在开始到此行尾的字符
[n]dd 删除从当前行开始的 n 行(准确来讲,是剪切,剪切不粘贴即为删除)
dG 删除光标所在开始到文件尾的所有字符
dw 删除光标开始位置的字,包含光标所在字符
d0(0为数字) 删除光标前本行所有内容,不包含光标所在字符
dgg 删除光标所在开始到文件首行第一个字符开始的所有字符

5)撤销恢复

按键 功能
.(点) 执行上一次操作
u 撤销前一个命令
ctrl+r 反撤销
100 + . 执行上一次操作100次

6)保存退出

按键 功能
ZZ(shift+z+z) 保存退出

7)查找

按键 功能
/字符串 从当前光标位置向下查找(n,N查找内容切换)
?字符串 从当前光标位置向上查找(n,N查找内容切换)

8)替换

按键 功能
r 替换当前字符
R 替换当前行光标后的字符(ESC退出替换模式)

9)可视模式

按键 功能
v 按字符移动,选中文本,可配合h、j、k、l选择内容,使用d删除,使用y复制
Shift + v 行选(以行为单位)选中文本,可配合h、j、k、l选择内容,使用d删除,使用y复制
Ctrl + v 列选 选中文本,可配合h、j、k、l选择内容,使用d删除,使用y复制

2. 末行模式下的操作

1)保存退出

按键 功能
:wq 保存退出
:x(小写) 保存退出
:w filename 保存到指定文件
:q 退出,如果文件修改但没有保存,会提示无法退出
:q! 退出,不保存
X 加密,取消密码 就是把输入密码为空 wq保存退出

all 表示所有

2)替换

按键 功能
: s/abc/123/ 光标所在行的第一个abc替换为123
: s/abc/123/g 光标所在行的所有abc替换为123
:1,10s/abc/123/g 将第一行至第10行之间的abc全部替换成123
:%s/abc/123/g 当前文件的所有abc替换为123
:%s/abc/123/gc 同上,但是每次替换需要用户确认
:1,$s/abc/123/g 当前文件的所有abc替换为123

3)分屏

按键 功能
:sp 当前文件水平分屏
:vsp 当前文件垂直分屏
: sp 文件名 当前文件和另一个文件水平分屏
: vsp 文件名 当前文件和另一个文件垂直分屏
ctrl-w-w 在多个窗口切换光标
:wall/:wqall/:qall 保存/保存退出/退出所有分屏窗口
vim -O a.c b.c 垂直分屏
vim -o a.c b.c 水平分屏

4) 其它用法(扩展)

按键 功能
:!man 3 printf 在vim中执行命令 (q退出)
:r !ls -l 将ls -l执行的结果写入当前文件中
:r /etc/passwd 将/etc/passwd文件中的内容写入到当前文件中
:w /tmp/txt 将当前文件内容写入到/tmp/txt文件中
:w! /tmp/txt(这里是绝对路径) 强制将当前文件内容写入到/tmp/txt文件中
:1,10s/^g 将第1行到10行行首添加// (^表示行首) //\转移字符
:1,10s#^#//#g 将第1行到10行行首添加// (#可以临时代替/ 分隔)
:%s/;/\r{\r\treturn0;\r}\r/g 将;替换成{ return 0; }
:1,10s#//##g 将第1行到10行行首去掉// (#可以临时代替/ 分隔)

5) 配置文件

局部配置文件(推荐)

xcc@machine:~/share/2nd$ vim ~/.vimrc

全局配置文件:

xcc@machine:~/share/2nd$ sudo vim /etc/vim/vimrc

七. GCC编译器简介

编辑器(如vi、记事本)是指我用它来写程序的(编辑代码),而我们写的代码语句,电脑是不懂的,我们需要把它转成电脑能懂的语句,编译器就是这样的转化工具。就是说,我们用编辑器编写程序,由编译器编译后才可以运行!

编译器是将易于编写、阅读和维护的高级计算机语言翻译为计算机能解读、运行的低级机器语言的程序。

gcc(GNU Compiler Collection,GNU 编译器套件),是由 GNU 开发的编程语言编译器。gcc原本作为GNU操作系统的官方编译器,现已被大多数类Unix操作系统(如Linux、BSD、Mac OS X等)采纳为标准的编译器,gcc同样适用于微软的Windows。

gcc最初用于编译C语言,随着项目的发展gcc已经成为了能够编译C、C++、Java、Ada、fortran、Object C、Object C++、Go语言的编译器大家族。

编译命令格式:

gcc [options] file…

g++ [options] file…

  • 命令、选项和源文件之间使用空格分隔
  • 一行命令中可以有零个、一个或多个选项
  • 文件名可以包含文件的绝对路径,也可以使用相对路径
  • 如果命令中不包含输出可执行文件的文件名,可执行文件的文件名会自动生成一个默认名,Linux平台为a.out,Windows平台为a.exe

八. GCC工作流程和常用选项

gcc编译器从拿到一个c源文件到生成一个可执行程序,中间一共经历了四个步骤:

四个步骤并不是gcc独立完成的,而是在内部调用了其他工具,从而完成了整个工作流程:

gcc工作的流程

xcc@machine:~/share/3rd/1gcc$ ls 1hello.c

第一步: 进行预处理

xcc@machine:~/share/3rd/1gcc$ gcc -E 1hello.c -o 1hello.i

第二步: 生成汇编文件

xcc@machine:~/share/3rd/1gcc$ gcc -S 1hello.i -o 1hello.s

第三步: 生成目标代码

xcc@machine:~/share/3rd/1gcc$ gcc -c 1hello.s -o 1hello.o

第四步: 生成可以执行文件

xcc@machine:~/share/3rd/1gcc$ gcc 1hello.o -o 1hello 第五步: 执行 xcc@machine:~/share/3rd/1gcc$ ./1hello hello itcast

LSB 小端存储,可查看我的C语言进阶博文

直接将源文件生成一个可以执行文件

xcc@machine:~/share/3rd/1gcc$ gcc 1hello.c -o 1hello xcc@machine:~/share/3rd/1gcc$ ./1hello hello itcast

如果不指定输出文件名字, gcc编译器会生成一个默认的可以执行a.out

xcc@machine:~/share/3rd/1gcc$ gcc 1hello.c
xcc@machine:~/share/3rd/1gcc$ ls 1hello 1hello.c 1hello.i 1hello.o 1hello.s a.out xcc@machine:~/share/3rd/1gcc$ ./a.out
hello itcast

gcc常用选项

选项 作用
-o file 指定生成的输出文件名为file
-E 只进行预处理
-S(大写) 只进行预处理和编译
-c(小写) 只进行预处理、编译和汇编
-v / --version 查看gcc版本号
-g 包含调试信息
-On n=0~3 编译优化,n越大优化得越多
-Wall 提示更多警告信息
-D 编译时定义宏

显示所有的警告信息

gcc -Wall test.c

将警告信息当做错误处理

gcc -Wall -Werror test.c

测试程序(-D选项):

#include<stdio.h>
int main()
{printf("SIZE%d\n",SIZE);return 0;
}

xcc@machine:~/test$ gcc 2test.c -DSIZE=10

xcc@machine:~/test$ ./a.out

SIZE: 10

九. 静态库和动态库简介

所谓“程序库”,简单说,就是包含了数据和执行码的文件。其不能单独执行,可以作为其它执行程序的一部分来完成某些功能。

库的存在可以使得程序模块化,可以加快程序的再编译,可以实现代码重用,可以使得程序便于升级。

程序库可分静态库(static library)和共享库(shared library)。

十. 静态连接和动态连接

链接分为两种:静态链接动态链接

1)静态链接

静态链接:由链接器在链接时将库的内容加入到可执行程序中。

优点:

  • 对运行环境的依赖性较小,具有较好的兼容性

缺点:

  • 生成的程序比较大,需要更多的系统资源,在装入内存时会消耗更多的时间
  • 库函数有了更新,必须重新编译应用程序

2)动态链接

动态链接:连接器在链接时仅仅建立与所需库函数的之间的链接关系,在程序运行时才将所需资源调入可执行程序。

优点:

  • 在需要的时候才会调入对应的资源函数
  • 简化程序的升级;有着较小的程序体积
  • 实现进程之间的资源共享(避免重复拷贝)

缺点:

  • 依赖动态库,不能独立运行
  • 动态库依赖版本问题严重

3)静态、动态编译对比

前面我们编写的应用程序大量用到了标准库函数,系统默认采用动态链接的方式进行编译程序,若想采用静态编译,加入-static参数。

以下是分别采用动态编译、静态编译时文件对比:

测试程序(test.c)如下:

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

编译:

xcc@machine:~/test$ gcc test.c -o test_share

xcc@machine:~/test$ gcc -static test.c -o test_static

结果对比:

十一. 静态库制作和使用

静态库可以认为是一些目标代码的集合,是在可执行程序运行前就已经加入到执行码中,成为执行程序的一部分。

按照习惯,一般以“.a”做为文件后缀名。静态库的命名一般分为三个部分:

  • 前缀:lib
  • 库名称:自己定义即可
  • 后缀:.a

所以最终的静态库的名字应该为:libxxx.a

1) 静态库制作

步骤1:将c源文件生成对应的.o文件

xcc@machine:~/test/3static_lib$ gcc -c add.c -o add.o

xcc@machine:~/test/3static_lib$ gcc -c sub.c -o sub.o

xcc@machine:~/test/3static_lib$ gcc -c mul.c -o mul.o

xcc@machine:~/test/3static_lib$ gcc -c div.c -o div.o

步骤2:使用打包工具ar将准备好的.o文件打包为.a文件 libtest.a

xcc@machine:~/test/3static_lib$ ar -rcs libtest.a add.o sub.o mul.o div.o

在使用ar工具是时候需要添加参数:rcs

  • r更新
  • c创建
  • s建立索引

2)静态库使用

静态库制作完成之后,需要将.a文件和头文件一起发布给用户。

假设测试文件为test.c,静态库文件为libtest.a头文件为XXX.h

编译命令:

xcc@machine:~/test/4static_test$ gcc test.c -L./ -I./ -ltest -o test

参数说明:

  • -L:表示要连接的库所在目录
  • -I./: I(大写i) 表示指定头文件的目录为当前目录
  • -l(小写L):指定链接时需要的库,去掉前缀和后缀

内部结构:

十二.动态库制作和使用

共享库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入。不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例,规避了空间浪费问题。

动态库在程序运行是才被载入,也解决了静态库对程序的更新、部署和发布页会带来麻烦。用户只需要更新动态库即可,增量更新。

按照习惯,一般以“.so”做为文件后缀名。共享库的命名一般分为三个部分:

  • 前缀:lib
  • 库名称:自己定义即可
  • 后缀:.so

所以最终的动态库的名字应该为:libxxx.so

1)动态库制作

步骤一:生成目标文件,此时要加编译选项:-fPIC(fpic)

xcc@machine:~/test/5share_lib$ gcc -fPIC -c add.c
xcc@machine:~/test/5share_lib$ gcc -fPIC -c sub.c

xcc@machine:~/test/5share_lib$ gcc -fPIC -c mul.c

xcc@machine:~/test/5share_lib$ gcc -fPIC -c div.c

参数:-fPIC 创建与地址无关的编译程序(pic,position independent code),是为了能够在多个应用程序间共享。

步骤二:生成共享库,此时要加链接器选项: -shared(指定生成动态链接库)

xcc@machine:~/test/5share_lib$ gcc -shared add.o sub.o mul.o div.o -o libtest.so

步骤三: 通过nm命令查看对应的函数

xcc@machine:~/test/5share_lib$ nm libtest.so | grep add 00000000000006b0 T add

xcc@machine:~/test/5share_lib$ nm libtest.so | grep sub 00000000000006c4 T sub

ldd查看可执行文件的依赖的动态库

xcc@machine:~/share/3rd/2share_test$ ldd test linux-vdso.so.1 => (0x00007ffcf89d4000) libtest.so => /lib/libtest.so (0x00007f81b5612000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f81b5248000) /lib64/ld-linux-x86-64.so.2 (0x00005562d0cff000)

2)动态库测试

引用动态库编译成可执行文件(跟静态库方式一样)

xcc@machine:~/test/6share_test$ gcc test.c -L. -I. -ltest (-I. 大写i -ltest 小写L)

然后运行:./a.out,发现竟然报错了!!!

  • 当系统加载可执行代码时候,能够知道其所依赖的库的名字,但是还需要知道绝对路径。此时就需要系统动态载入器(dynamic linker/loader)。
  • 对于elf格式的可执行程序,是由ld-linux.so*来完成的,它先后搜索elf文件的 DT_RPATH段 — 环境变量LD_LIBRARY_PATH — /etc/ld.so.cache文件列表 — /lib/, /usr/lib目录找到库文件后将其载入内存。

3)如何让系统找到动态库

  • 拷贝自己制作的共享库到/lib或者/usr/lib(不能是/lib64目录)—》不推荐
  • 临时设置LD_LIBRARY_PATH:(pwd查看当前路径)

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:库路径

  • 永久设置,把export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:库路径,设置到~/.bashrc或者 /etc/profile文件中

    xcc@machine:~/share/3rd/2share_test$ vim ~/.bashrc

    最后一行添加如下内容:

    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/deng/share/3rd/2share_test

    使环境变量生效

    xcc@machine:~/share/3rd/2share_test$ source ~/.bashrc

    xcc@machine:~/share/3rd/2share_test$ ./test
    a + b = 20 a - b = 10

  • 将其添加到 /etc/ld.so.conf文件中

    编辑/etc/ld.so.conf文件,加入库文件所在目录的路径

    运行sudo ldconfig -v,该命令会重建/etc/ld.so.cache文件

    xcc@machine:~/share/3rd/2share_test$ sudo vim /etc/ld.so.conf

    文件最后添加动态库路径(绝对路径)

    使生效

    xcc@machine:~/share/3rd/2share_test$ sudo ldconfig -v

  • 使用符号链接, 但是一定要使用绝对路径

    xcc@machine:~/test/6share_test$ sudo ln -s /home/deng/test/6share_test/libtest.so /lib/libtest.so

十三. GDB调试器

1. GDB简介

GNU工具集中的调试器是GDB(GNU Debugger),该程序是一个交互式工具,工作在字符模式。

除gdb外,linux下比较有名的调试器还有xxgdb, ddd, kgdb, ups。

GDB主要帮忙你完成下面四个方面的功能:

  1. 启动程序,可以按照你的自定义的要求随心所欲的运行程序。
  2. 可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式)
  3. 当程序被停住时,可以检查此时你的程序中所发生的事。
  4. 动态的改变你程序的执行环境。

2. 生成调试信息

一般来说GDB主要调试的是C/C++的程序。要调试C/C++的程序,首先在编译时,我们必须要把调试信息加到可执行文件中。使用编译器(cc/gcc/g++)的 -g 参数可以做到这一点。如:

gcc -g hello.c -o hello

g++ -g hello.cpp -o hello

如果没有-g,你将看不见程序的函数名、变量名,所代替的全是运行时的内存地址。

3. 启动GDB

#include <stdio.h>int main(int argc, char **argv)
{int i = 0;//将传入参数全部输出for (i = 0; i < argc; i++){printf("argv[%d]: %s\n", i, argv[i]); }printf("hello itcast\n");return 0;
}
  • 启动gdb:gdb program

    program 也就是你的执行文件,一般在当前目录下。

  • 设置运行参数

    set args 可指定运行时参数。(如:set args 10 20 30 40 50 )

    show args 命令可以查看设置好的运行参数。

  • 启动程序

    run: 程序开始执行,如果有断点,停在第一个断点处

    start: 程序向下执行一行。

4. 显示源代码

用list命令来打印程序的源代码。默认打印10行。

Ø list linenum: 打印第linenm行的上下文内容.

Ø list function: 显示函数名为function的函数的源程序。

Ø list: 显示当前行后面的源程序。

Ø list -: 显示当前行前面的源程序。

一般是打印当前行的上5行和下5行,如果显示函数是是上2行下8行,默认是10行,当然,你也可以定制显示的范围,使用下面命令可以设置一次显示源程序的行数。

Ø set listsize count:设置一次显示源代码的行数。

Ø show listsize: 查看当前listsize的设置。

5. 断点操作

1)简单断点

break 设置断点,可以简写为b

Ø b 10 设置断点,在源程序第10行

Ø b func 设置断点,在func函数入口处

2)多文件设置断点

C++中可以使用class::function或function(type,type)格式来指定函数名。

如果有名称空间,可以使用namespace::class::function或者function(type,type)格式来指定函数名。

Ø break filename:linenum – 在源文件filename的linenum行处停住

Ø break filename:function – 在源文件filename的function函数的入口处停住

Ø break class::function或function(type,type) – 在类class的function函数的入口处停住

Ø break namespace::class::function – 在名称空间为namespace的类class的function函数的入口处停住

3)查询所有断点

  • info b
  • info break
  • i break
  • i b

6. 条件断点

一般来说,为断点设置一个条件,我们使用if关键词,后面跟其断点条件。

设置一个条件断点:

b test.c:8 if Value == 5

7. 维护断点

1)delete [range…] 删除指定的断点,其简写命令为d。

  • 如果不指定断点号,则表示删除所有的断点。range表示断点号的范围(如:3-7)。
  • 比删除更好的一种方法是disable停止点,disable了的停止点,GDB不会删除,当你还需要时,enable即可,就好像回收站一样。

2) disable [range…] 使指定断点无效,简写命令是dis。

如果什么都不指定,表示disable所有的停止点。

3) enable [range…] 使无效断点生效,简写命令是ena。

如果什么都不指定,表示enable所有的停止点。

8. 调试代码

  • run 运行程序,可简写为r
  • next 单步跟踪,函数调用当作一条简单语句执行,可简写为n
  • step 单步跟踪,函数调进入被调用函数体内,可简写为s
  • finish 退出进入的函数
  • until 在一个循环体内单步跟踪时,这个命令可以运行程序直到退出循环体,可简写为u。
  • continue 继续运行程序,停在下一个断点的位置,可简写为c
  • quit 退出gdb,可简写为q

9. 自动显示

你可以设置一些自动显示的变量,当程序停住时,或是在你单步跟踪时,这些变量会自动显示。相关的GDB命令是display。

  • display 变量名
  • info display – 查看display设置的自动显示的信息。
  • undisplay num(info display时显示的编号)
  • delete display dnums… – 删除自动显示,dnums意为所设置好了的自动显式的编号。如果要同时删除几个,编号可以用空格分隔,如果要删除一个范围内的编号,可以用减号表示(如:2-5)
  • disable display dnums…启用
  • enable display dnums…禁用
  • disable和enalbe不删除自动显示的设置,而只是让其失效和恢复。

10. 查看修改变量的值

1)ptype width – 查看变量width的类型

type = double

2)p width – 打印变量width 的值

$4 = 13

你可以使用set var命令来告诉GDB,width不是你GDB的参数,而是程序的变量名,如:

set var width=47 // 将变量var值设置为47

在你改变程序变量取值时,最好都使用set var格式的GDB命令

11. 数据查看

1)查看运行时数据

print 打印变量、字符串、表达式等的值,可简写为p

p count 打印count的值

扩展

一.静态链接库、动态链接库(C/C++)

平时我们写程序都必须include很多头文件,因为可以避免重复造轮子,软件大厦可不是单靠一个人就能完成的。但是你是否知道引用的那些头文件中的函数是怎么被执行的呢?这就要牵扯到链接库了!!!

库有两种,一种是静态链接库,一种是动态链接库,不管是哪一种库,要使用它们,都要在程序中包含相应的include头文件。我们先来回顾一下程序编译的过程。如下图:

我们结合gcc指令来看一下每个阶段生成的文件:

gcc -c helloWorld.c

生成一个helloWorld.o文件,该文件是将源文件编译成的汇编文件,在链接之前,该文件不是可执行文件。

gcc -o helloWorld helloWorld.c

生成的是一个helloWorld的执行文件,格式为ELF(与windows不一样)。该文件为链接后的可执行文件。

1.静态链接库

什么是静态链接呢?即在链接阶段,将源文件中用到的库函数与汇编生成的目标文件.o合并生成可执行文件。该可执行文件可能会比较大。

这种链接方式的好处是:方便程序移植,因为可执行程序与库函数再无关系,放在如何环境当中都可以执行。

缺点是:文件太大,一个全静态方式生成的简单print文件都有857K。而动态链接生成的一样的可执行文件却只要8.4K。

文件内容很简单,就是一个printf("hello world!\n");

因为包含库文件stdio,所以静态编译出的文件很大。如果你想尝试的话,可以这样编译:

gcc -static -o print print.c

在linux中,静态库为lib*.a,动态库为lib*.so。
下面我们来写一个库文件,然后生成一个静态库,然后尝试着调用一下它。

一个简单的add函数,头文件为

头文件对于的源文件:

下面我们来生成静态:

输入:g++ -c add.cpp 生成.o目标文件

然后用ar命令进一步生成库libadd.a:

ar -crv libadd.a  add.o

这样就生成了一个静态链接库libadd.a。

下面我们来写一个测试文件:

<span style="font-size:18px;">#include <iostream>
#include "./addlib/add.h"
using namespace std;int main()
{int number1 = 10;int number2 = 90;cout << "the result is " << add(number1, number2) << endl;return 0;
}</span>

因为我的目录结构是add.cpp, addlib(文件夹),在addlib中是头文件和静态库,所以include用相对路径找到头文件add.h。
下面我们编译一下该文件:

g++ -o test test.cpp -L./addlib -ladd

-L是指定加载库文件的路径
-l是指定加载的库文件。

运行一下:

可见调用成功。

2.动态链接库

我们知道静态链接的话,文件会很大,往往实现很小的一个功能就需要占用很大的空间,而且每次库文件升级的话,都要重新编译源文件,很不方便。

具体下面如下:

对于静态编译的程序1和程序2,都应用库staticMath。在内存中就又两份相同的staticMath目标文件,很浪费空间,一旦程序数量过多就很可能会内存不足。

这么大的内存才只能运行这几个程序,实在不甘心。

这样就又了动态库发挥威力的地方了。我们来看看动态链接的结果:

我们看到在这种模型中,两个程序只应用一个库,这个目标文件在内存中只有一份,供所有程序使用。

并且在程序运行过程中动态调用库文件,很方便,又不占空间,但是动态链接有一个缺点就是可移植性太差,如果两台电脑运行环境不同,动态库存放的位置不一样,很可能导致程序运行失败。

在具体的应用中,静态与动态应当合理选择!!!

下面我们来生成一个动态库:

输入:g++ -fPIC -shared -o libadd.so add.cpp

这样就生成了一个libadd.so的动态库。

下面我们用动态链接的方式编译test.cpp。

输入:g++ -o test test.cpp -L./addlib -ladd

该命令和刚刚静态链接一样。注意-l后面接的是lib与so中间的库名称。

我们执行一下:

发现不行,因为执行程序找不到libadd.so。

可以看到test执行程序用到的libadd.so没有找到。。。

原因是在/etc/ld.so.conf文件中设置了动态链接库了寻找路径。

可以看到有很多路径设置文件,在ld.so.conf.d中,我们在下面添加一下我们libadd.so的路径。

然后再执行一下ldconfig命令。

这下就可以成功执行test文件了。

注意一下,有人说为什么我程序中extern int number;可以直接编译不需要什么静态链接库,动态链接库。那是因为你在链接时已经将number变量定义的目标文件.o和源文件进行了链接,如:gcc -o main main.o test.o。如果你只是单纯的用main.o进行链接,是生成不了可执行目标文件的,如:gcc -o main main.c会报告未定义的number引用。

综上说述,静态和动态链接库的选择要视情况而定。一般比较推荐动态链接方式,因为可以很好的节约内存,而且方便以后的库文件升级。

g++(gcc)编译选项

  • l -shared :指定生成动态链接库。

  • -static :指定生成静态链接库。

  • -fPIC :表示编译为位置独立的代码,用于编译共享库。目标文件需要创建成位置无关码,念上就是在可执行程序装载它们的时候,它们可以放在可执行程序的内存里的任何地方。

  • -L. :表示要连接的库所在的目录。

  • -l:指定链接时需要的动态库。编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.a/.so来确定库的名称。

  • -Wall :生成所有警告信息。

  • -ggdb :此选项将尽可能的生成gdb的可以使用的调试信息。

  • -g :编译器在编译的时候产生调试信息。

  • -c :只激活预处理、编译和汇编,也就是把程序做成目标文件(.o文件)。

  • -Wl,options :把参数 (options) 传递给链接器 ld 。如果 options 中间有逗号 , 就将 options 分成多个选项 , 然后传递给链接程序。

Linux系统编程-vim-gcc-动态库静态库相关推荐

  1. 【Linux系统编程学习】 动态库的制作与使用

    此为牛客网Linux C++课程1.6&1.7 的课程笔记. 1. 动态库命名规则 2. 动态库的制作 第一步,用gcc编译生成.o目标文件,注意要用-fpic参数生成与位置无关的代码: 第二 ...

  2. 学习系统编程No.14【动静态库】

    引言: 北京时间:2023/4/3/7:06,刚刚晨跑回来,为了摆脱困意,刷了一下视屏,哈哈哈!我发现我每次刷视屏都是被迫的,都是看到某个感兴趣的标题,然后点进去一看,就不能自拔了,所以我下次得把消息 ...

  3. alin的学习之路(Linux系统编程:三)(vim,gcc,库,gdb)

    alin的学习之路(Linux系统编程:三)(vim,gcc,库,gdb) 1.vim的使用 vim有三种模式:命令模式,末行模式,编辑模式 光标的移动[命令模式] h 向左 ,j 向下,k 向上,l ...

  4. Linux系统编程 25 动态库和静态库 理论对比

    Linux系统编程 25 动态库和静态库 理论对比 库分为两类 1.静态库 2.动态库(共享库) 静态库 是在可执行程序运行前就已经加入到执行码中, 成为执行程序的一部分 共享库(动态库) 执行程序启 ...

  5. Linux系统编程25:基础IO之亲自实现一个动静态库

    本文接:Linux系统编程24:基础IO之在Linux下深刻理解C语言中的动静态库以及头文件和库的关系 文章目录 A:说明 B:实现静态库 C:实现动态库 A:说明 前面说过,库其实就是头文件和和.a ...

  6. linux系统应用学习(三)--- 动态库静态库

    动态库静态库 库文件:一般指第三方提供的可调用的库函数文件,库文件封存的是函数体,即.c文件里面的内容. 动态库      静态库 Windows下:        xx.dll            ...

  7. Linux基础——gcc编译、静态库与动态库(共享库)

    Linux基础--gcc编译.静态库与动态库(共享库) https://blog.csdn.net/daidaihema/article/details/80902012 Linux基础--gcc编译 ...

  8. linux库--静态库、动态库

    文章目录 一.分文件编程思想 二.动态库静态库 1.概念介绍 2.静态库的制作和使用 3.动态库的制作和使用 一.分文件编程思想 好处: 分模块的编程思想 例如: 网络 a 超声波b 电机c a.功能 ...

  9. linux系统下用GCC、JAVA和Python编程

    一:linux系统下用GCC编程 方法一: 1.C语言文件建立 [root@localhost kang]# vim tang.c 2.编写代码 代码输入后,按下shift+;打出冒号输入wq按回车保 ...

  10. linux库引入之动态库静态库(生成和使用)

    库: 库是一种可执行代码的二进制形式,可以被操作系统载入内存执行.就是将源代码转化为二进制格式的源代码,相当于进行了加密,别人可以使用库,但是看不到库中的内容. 如何使用 用户需要同时具有头文件和库. ...

最新文章

  1. SAP S4HANA如何取到采购订单ITEM里的'条件'选项卡里的条件类型值?
  2. Smali文件添加try/catch语句,出现“invalid use of move-exception”异常
  3. MySQL给用户设置密码(修改密码)、创建用户,grant为某个IP、某个网段或所有IP地址创建访问用户并授权
  4. 弹性理论法研究桩基受力计算公式_竖向荷载下群桩的承载力分析
  5. java 验证码_如何使用Java生成随机验证码
  6. linux java测试工具_Linux下Java虚拟机状态监测工具
  7. java实现同步的两种方式
  8. (HoneyView)轻便好用的免费图片浏览器
  9. 面试真题:经典智力题最详汇总(上)
  10. Python3+selenium+BaiduAI识别并下载花瓣网高颜值妹子图片
  11. 如何修改apk文件,改之理简单使用教程
  12. 无人机运动规划4:ego-swarm无人机群运动规划
  13. 这竟然是全世界最好的模式(商业大佬为之咂舌)
  14. 免费好用的英语单词统计软件(带翻译功能)
  15. MSP430(CCS工程下)添加printf实现打印功能
  16. 湖北商贸学院计算机二级领取,湖北商贸学院教务管理系统入口http://jw.hbc.edu.cn/...
  17. php安全开发正则表达式,动态网页制作PHP常用的正则表达式
  18. node.js+mysql实现分库分表存查数据:
  19. 洛谷P3352 [ZJOI2016]线段树
  20. 电子课件html咋阅读,html教学课件

热门文章

  1. 手机刷机、root等经验
  2. android系统的优缺点
  3. PowerISO v5.1
  4. Keeping up with recently research: 在ACM和IEEE中订阅最新的研究进展
  5. 《烈火如歌》书写悱恻爱情 原著小说上线书旗小说
  6. 大爱无疆|CBK进军国际市场,为中国民企崛起而不懈努力
  7. Spring中的IoC(控制反转)和DI(依赖注入)
  8. Linux 文档编辑 : pico 命令详解
  9. 艾为电子年盈利1亿元:同比增速大幅下滑,科创板IPO暂时中止
  10. Android 蓝牙服务