280 likes | 569 Views
Linux 下 gcc 编程简介. 主要内容. 1 vi 使用 2 gcc 简介 3 gcc 编译程序过程 4 库的连接以及制作 5 makefile 简介 6 autoconf and automake 简介 7 gdb( 程序调试 ). Vi 基本操作. 1vi(vim) 背景 2 基本命令 (1) 进入 vi filename (2) 编辑模式 命令行模式 转换方式 i Esc (3) 保存 w 保存退出 x 退出 q 不保存文件退出 q!
E N D
主要内容 • 1 vi使用 • 2 gcc简介 • 3 gcc编译程序过程 • 4 库的连接以及制作 • 5 makefile简介 • 6 autoconf and automake简介 • 7 gdb(程序调试)
Vi基本操作 • 1vi(vim)背景 • 2基本命令 (1) 进入 vi filename (2) 编辑模式 命令行模式 转换方式 i Esc (3)保存w 保存退出x 退出q 不保存文件退出q! (4)查找 替换 / ; ?; :s/oldstr/newstr;g(globle)
(5)复制 粘贴 移动 删除 yy p P m x d dd co (6)光标移动k j h l H L 0 $ ^ (7)行号 Vim高亮显示, :set nu (8)Undo redo u (.)
gcc • 1GNU Compiler Collection • 2 gcc的组件和软件工具 • 3 GCC的强大之处就在于它允许你在任何一个过程中停下来查看中间结果,并对其加以控制 • 4 宿主编译 ,交叉编译 • 5 优化,对不同结构计算机优化 • 6 编译效率高
Gcc编译过程 • 使用GCC编译程序时,编译过程可以被细分为四个阶段: • ◆ 预处理(Pre-Processing) • ◆ 编译(Compiling) • ◆ 汇编(Assembling) • ◆ 链接(Linking)
.i 为后缀的文件,是已经预处理过的C源代码文件; • .ii为后缀的文件,是已经预处理过的C++源代码文件; • .o为后缀的文件,是编译后的目标文件; • .s为后缀的文件,是汇编语言源代码文件; • .S为后缀的文件,是经过预编译的汇编语言源代码文件。
Gcc主要参数 • -o 定义输出文件 • -E 完成预处理/预编译停止 • -c 只编译生成.o,不连接 • -g gdb调试用,在可执行程序中包含标准调试信息 • -O,O1,O2,O3,O4,O5 优化级别 • -w 关闭所有警告 • -Wall 允许所有有用的警告
-DFOO=BAR 定义预处理宏FOO的值为BAR • -IDIRNAME 将DIRNAME加入到包含文件的搜索目录中去 • -LDIRNAME 将DIRNAME加入到库文件文件的搜索目录中去 • -lFOO 动态连接库,名为libFOO.o/libFOO.so • -mcpu=CPU TYPE 针对不同CPU作不同的优化,如-m486,-mpentiumpro
库 • 静态 .a archive(归档文件) • 动态(共享) .so(.dll) • 库(Library)就是一组已经写好了的函数和变量、经过编译代码,是为了能够提高开发效率和运行效率而设计的 • gcc的命令行参数(-I, -L)
(1)静态库 • 静态是指每个用到该库的应用程序都拥有一份自己的库拷贝;应用程序运行的时候,即使将库删除也没有问题,因为应用程序自己已经有了自己的拷贝。 • (2)共享库 • 一个共享库有可能被多个所有应用程序共享。因此,对每个应用程序来说,即使不再使用某个共享库,也不应将其删除.
关于使用库的问题 • 默认情况下,gcc会自动搜索下面的路径: • 对头文件: • /usr/local/include/ • /usr/include/ • 对库文件: • /usr/local/lib/ • /usr/lib/ LIBRARY_PATH=/opt/lib export LIBRARY_PATH(设置环境变量方式)
库生成的问题 • 生成静态库的方法 • $ gcc -c gdfontwu.c • $ gcc -c gdfontliu.c • $ gcc -c gdfontbin.c • $ ar rc libgdfont.a gdfontwu.o gdfontliu.o gdfontbin.o
生成动态库的方法 • $ gcc -c gdfontwu.c • $ gcc -c gdfontliu.c • $ gcc -c gdfontbin.c • $ gcc -o libgdfont.so -shared -fPIC gdfontwu.o gdfontliu.o gdfontbin.o -fPIC:表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程需要,而不能达到真正代码段共享的目的
Makefile简介 • 一种编译规则,能够实现自动化编译, • makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令..一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率
Makefile里主要包含了五个东西:显式规则、隐晦规则、变量定义、文件指示和注释。1、显式规则。显式规则说明了,如何生成一个或多的的目标文件。这是由Makefile的书写者明显指出,要生成的文件,文件的依赖文件,生成的命令。2、隐晦规则。由于我们的make有自动推导的功能,所以隐晦的规则可以让我们比较粗糙地简略地书写Makefile,这是由make所支持的。3、变量的定义。在Makefile中我们要定义一系列的变量,变量一般都是字符串,这个有点你C语言中的宏,当Makefile被执行时,其中的变量都会被扩展到相应的引用位置上。4、文件指示。其包括了三个部分,一个是在一个Makefile中引用另一个Makefile,就像C语言中的include一样;另一个是指根据某些情况指定Makefile中的有效部分,就像C语言中的预编译#if一样;还有就是定义一个多行的命令。有关这一部分的内容,我会在后续的部分中讲述。5、注释。Makefile中只有行注释,和UNIX的Shell脚本一样,其注释是用“#”字符,这个就像C/C++中的“//”一样。如果你要在你的Makefile中使用“#”字符,可以用反斜框进行转义,如:“\#”。最后,还值得一提的是,在Makefile中的命令,必须要以[Tab]键开始。Makefile里主要包含了五个东西:显式规则、隐晦规则、变量定义、文件指示和注释。1、显式规则。显式规则说明了,如何生成一个或多的的目标文件。这是由Makefile的书写者明显指出,要生成的文件,文件的依赖文件,生成的命令。2、隐晦规则。由于我们的make有自动推导的功能,所以隐晦的规则可以让我们比较粗糙地简略地书写Makefile,这是由make所支持的。3、变量的定义。在Makefile中我们要定义一系列的变量,变量一般都是字符串,这个有点你C语言中的宏,当Makefile被执行时,其中的变量都会被扩展到相应的引用位置上。4、文件指示。其包括了三个部分,一个是在一个Makefile中引用另一个Makefile,就像C语言中的include一样;另一个是指根据某些情况指定Makefile中的有效部分,就像C语言中的预编译#if一样;还有就是定义一个多行的命令。有关这一部分的内容,我会在后续的部分中讲述。5、注释。Makefile中只有行注释,和UNIX的Shell脚本一样,其注释是用“#”字符,这个就像C/C++中的“//”一样。如果你要在你的Makefile中使用“#”字符,可以用反斜框进行转义,如:“\#”。最后,还值得一提的是,在Makefile中的命令,必须要以[Tab]键开始。
autoconf and automake • autoconf和automake两个工具来帮助我们自动地生成符合自由软件惯例的Makefile,这样就可以象常见的GNU程序一样,只要使用“./configure”,“make”,“make instal aclocal; autoconf; automake --add-missing; ./configure; make; ./helloworld
gdb • 1 help 命令 • 2 tab键的使用,1次,2次 • 3 查看源文件 list 搜索代码 search向前 reverse-search全部 指定源文件路径directory dir • 4 程序运行 r/run • 5 set show info
set listsize 设置一次显示源代码的行数 show listsize 查看当前listsize的设置。 info args 打印出当前函数的参数名及其值 info locals 当前函数中所有局部变量及其值 show directories 显示定义了的源文件搜索路径
6 设置断点(breakpoint) • 7 设置观察点(watchpoint) 与断点区别 观察点一般来观察某个表达式(变量也是一种表达式)的值是否有变化了,如果有变化,马上停住程序 • 8 设置捕捉点(catchpoint) 什么是捕捉点? 你可设置捕捉点来补捉程序运行时的一些事件当event发生时,停住程序 • 9 清除断点 delete、clear、disable、enable • 10 设置条件断点b func if i==3 • 11 断点菜单 同名函数,参数不同,选择那个函数
(gdb) b String::after[0] cancel[1] all[2] file:String.cc; line number:867[3] file:String.cc; line number:860[4] file:String.cc; line number:875[5] file:String.cc; line number:853[6] file:String.cc; line number:846[7] file:String.cc; line number:735> 2 4 6Breakpoint 1 at 0xb26c: file String.cc, line 867.Breakpoint 2 at 0xb344: file String.cc, line 875.Breakpoint 3 at 0xafcc: file String.cc, line 846.Multiple breakpoints were set.Use the "delete" command to delete unwantedbreakpoints.(gdb)
12 恢复运行单步调试 continue c setp s next finish untile u setpi/ nexti(单步机器指令) • 13 查看栈信息 bt backtrace -n(n层栈) frame n up down • 14 disassemble 可以查看源程序的当前执行时的机器码 disassemble func • 15 查看运行时数据 表达式 程序变量 数组 输出格式 查看内存 自动显示 查看寄存器 • 16 改变程序执行 修改变量值 跳转执行 产生信号量 强制函数返回 强制调用函数
print 变量;print 表达式 p /x n 你可以设置一些自动显示的变量,当程序 住时,或是在你单步跟踪时,这些变量会 动显示。相关的GDB命令是display。displaydisplay/display/ • 查看内存 • 你可以使用examine命令(简写是x)来查看内存地址中的值。x命令的语法如下所示: • x/ • n、f、u是可选的参数。 • n 是一个正整数,表示显示内存的长度,也就是说从当前地址向后显示几个地址的内容。 • f 表示显示的格式,参见上面。如果地址所指的是字符串,那么格式可以是s,如果地十是指令地址,那么格式可以是i。 • u 表示从当前地址往后请求的字节数,如果不指定的话,GDB默认是4个bytes。 • u参数可以用下面的字符来代替, • b表示单字节, • h表示双字节, • w表示四字节, • g表示八字节。 • 当我们指定了字节长度后,GDB会从指内存定的内存地址开始,读写指定字节,并把其当作一个值取出来。
输出格式一般来说,GDB会根据变量的类型输出变量的值。但你也可以自定义GDB的输出的格式。例如,你想输出一个整数的十六进制,或是二进制来查看这个整型变量的中的位的情况。要做到这样,你可以使用GDB的数据显示格式:x 按十六进制格式显示变量。d 按十进制格式显示变量。u 按十六进制格式显示无符号整型。o 按八进制格式显示变量。t 按二进制格式显示变量。a 按十六进制格式显示变量。c 按字符格式显示变量。f 按浮点数格式显示变量
查看寄存器要查看寄存器的值,很简单,可以使用如下命令:info registers查看寄存器的情况。(除了浮点寄存器)info all-registers查看所有寄存器的情况。(包括浮点寄存器)info registers查看所指定的寄存器的情况。寄存器中放置了程序运行时的数据,比如程序当前运行的指令地址(ip),程序的当前堆栈地址(sp)等等。你同样可以使用print命令来访问寄存器的情况,只需要在寄存器名字前加一个$符号就可以了。如:p $eip
数组有时候,需要查看一段连续的内存空间的值。比如数组的一段,或是动态分配的数据的大小。你可以使用GDB的“@”操作符,“@”的左边是第一个内存的地址的值,“@”的右边则你你想查看内存的长度。例如,你的程序中有这样的语句:int *array = (int *) malloc (len * sizeof (int));于是,在GDB调试过程中,你可以以如下命令显示出这个动态数组的取值:p *array@len@的左边是数组的首地址的值,也就是变量array所指向的内容,右边则是数据的长度,其保存在变量len中,其输出结果,大约是下面这个样子的:(gdb) p *array@len$1 = {2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40}如果是静态数组的话,可以直接用print数组名,就可以显示数组中所有数据的内容了
基本gdb命令: • --------------------------------------------------------------------- • 命令 简写 功能 • --------------------------------------------------------------------- • file 装入想要调试的可执行文件. • kill k 终止正在调试的程序. • list l 列出产生执行文件的源代码的一部分. • next n 执行一行源代码但不进入函数内部. • step s 执行一行源代码而且进入函数内部. • continue c 继续执行程序,直至下一中断或者程序结束。 • run r 执行当前被调试的程序. • quit q 终止 gdb. • watch 使你能监视一个变量的值而不管它何时被改变. • catch 设置捕捉点. • thread t 查看当前运行程序的线程信息. • break b 在代码里设置断点, 这将使程序执行到这里时被挂起. • make 使你能不退出 gdb 就可以重新产生可执行文件. • shell 使你能不离开 gdb 就执行 UNIX shell 命令. • print p 打印数据内容。 • examine x 打印内存内容。 • backtrace bt 查看函数调用栈的所有信息
其他讨论 • KDevelop Qt • Linux java • Linux 安全 稳定 多用户 可配置 开源 移值性强 网络支持 • Linux 替代 windows • Linux 服务器 • Linux 缺点….