Lin 基础技术教程 6_第1页
Lin 基础技术教程 6_第2页
Lin 基础技术教程 6_第3页
Lin 基础技术教程 6_第4页
Lin 基础技术教程 6_第5页
已阅读5页,还剩47页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第6章常用开发工具主要内容C语言的编译过程gcc命令行选项gdb程序调试工具和应用示例make程序维护工具6.1gcc编译系统Linux平台上目前最常用的C语言编译系统是gcc(GNUCompilerCollection),它是GNU项目中符合ANSIC标准的编译系统,能够编译用C,C++和Objective-C等语言编写的程序。6.1.1文件扩展名Linux系统用后缀来区分不同类型的文件。在gcc命令行上可以使用有不同后缀的文件。常用的文件名后缀及其表示的文件类型表6-1

常用文件扩展名及其表示的文件类型文件扩展名文

型.cC语言源文件.i预处理后的C语言源文件.ii预处理后的C++语言源文件.C、.cc、.cp、.cpp、.c++、.cxxC++语言源文件.mObjective-C语言源文件.mi预处理后的Objective-C语言源文件.F、.fpp、.FPPFORTRAN语言源文件.s汇编程序文件.S必须预处理的汇编程序文件.o目标文件.a静态链接库.so动态链接库.h头文件6.1.2C语言编译过程gcc编译程序时,其编译过程可以分为4个阶段:预处理(Preprocessing)编译(Compiling)汇编(Assembling)连接(Linking)1.预处理阶段①将以#include行所指出的文件替代该指令行②对C语言源程序中的所有宏名进行宏替换③对条件编译指令将根据有关的条件,把某些代码滤掉,使之不进行编译④对于源程序中出现的_LINE_,_FILE_等预先定义好的宏名,将用合适的值进行替换;对#line,#error和#pragma分别进行相应处理。2.编译阶段对预处理之后的输出文件进行词法分析和语法分析,将其“翻译”为功能等价的中间代码表示或汇编代码3.汇编过程汇编程序(Assembler)把汇编语言代码翻译成目标机器代码的过程4.连接阶段使有关的目标文件连成一个整体,最终成为可被操作系统执行的可执行文件。连接模式分为静态连接和动态连接。6.1.3gcc命令行选项1.预处理选项表6-2

预处理阶段常用选项及其功能选

项功

能-C在预处理后的输出中保留源文件中的注释-Dname定义一个宏name,且其值为1-Dname=definition定义一个宏name,并指定其值为definition。它的作用等价于在源文件中使用宏定义指令“#definenamedefinition”,但-D选项的优先级高于宏定义指令,可以覆盖源文件中的定义-Uname取消之前对name的任何定义,无论其是内置的还是由-D选项提供的-Idir指定搜索头文件的路径dir。先在指定的路径中搜索要包含的头文件,若找不到,则在标准路径(/usr/include、/usr/lib及当前工作目录)中搜索-ofile将输出写到file指定的文件中,该选项等价于将file作为cpp的第2个非选项参数(预处理后的输出文件)-E仅对指定的源文件进行预处理,不进行编译操作,生成的结果将输到标准输出文件中2.编译选项选项格式功

能-c只生成目标文件,不进行连接。用于对源文件的分别编译-S只进行编译,不做汇编,生成汇编代码文件格式,其名与源文件相同,但扩展名为.s-ofile将输出放在文件file中。如果未使用该选项,则可执行文件放在a.out中-g指示编译程序在目标代码中加入供调试程序gdb使用的附加信息-v在标准出错输出上显示编译阶段所执行的命令,即编译驱动程序及预处理程序的版本号gcc编译程序常用选项及其作用举例:gcc编译程序选项的作用$catmeng1.c#include<stdio.h>main(){intr;printf("Enteraninteger,please!\n");scanf("%d",&r);square(r);return0;}$catmeng2.c#include<stdio.h>intsquare(intx){printf("Thesquare=%d\n",x*x);return(x*x);}$gccmeng1.cmeng1.c:7:4:warning:implicitdeclarationoffunction‘square’[-Wimplicit-function-declaration]7|square(r); |^~~~~~/usr/bin/ld:/tmp/ccSXPGJv.o:infunction`main':meng1.c:(.text+0x46):undefinedreferenceto`square'collect2:error:ldreturned1exitstatus这个错误表明,文件meng1.c中函数main调用了函数square,但在该文件中未定义square。所以,不带选项就直接编译meng1.c是不行的。$gcc-cmeng1.c$gcc-cmeng2.c$gccmeng1.omeng2.o-omeng12$./meng12Enteraninteger,please!123Thesquare=151293.优化选项表6-4

优化程序常用的选项及其功能选

项功

能-O尝试减少代码并缩短执行时间,但不执行任何需要花费大量编译时间的优化-O1-O2在-O1级别的优化基础上进行额外调整工作——除不进行循环展开、函数内联和寄存器重新命名外,几乎进行所有可选优化-O3除了完成所有-O2级别的优化,还需包括循环展开和其他一些与处理器特性相关的优化工作-O0缩短编译时间,并使调试产生预期结果。这是默认设置-Os具有-O2级别的优化效果,同时不会显著增加代码大小4.连接选项表6-5

连接程序常用的选项及其功能选

项功

能object-file-name若文件名不以专用扩展名结尾,则将其视为目标文件名或库名。连接程序可以根据文件内容区分目标文件和库文件-c、-S、-E若使用其中任意一个选项,则不运行连接程序,且目标文件名不应作为参数-llibrary连接时搜索由library命名的库。连接程序按照命令行指定的顺序搜索并处理库及目标文件。实际的库名是liblibrary,但按默认规则,开头的lib和扩展名(.a或.so)可以省略-static在支持动态连接的系统中,强制使用静态链接库,禁止连接动态库;在其他系统中此选项无效-Ldir将指定目录dir添加到连接程序搜索库文件的路径表中,即在搜索-l选项后面列举的库文件时,先到dir目录下搜索,未找到再到标准位置搜索-Bprefix用于指定查找可执行文件、库文件、包含文件和编译程序本身数据文件的路径-ofile指定连接程序最后生成的可执行文件名为file,而非默认的a.outLinux系统下库文件的命名有一个约定,所有的库名都以lib开头。因此,在-l选项所指定的文件名前自动地插入lib。约定:以.a结尾的库是静态库,以.so结尾的库是动态库静态库是目标文件的集合,生成静态库的方法分为两步:①将各函数的源文件编译成目标文件。

例如:$gcc-cf1.cf2.cf3.c-ogame.o

由此可得到各源文件的目标文件game.o。②使用ar工具将目标文件收集起来,放到一个归档文件中。

例如:$ar-rcs$HOME/lib/libgame.agame.o它创建静态库libgame.a,库的内容由列出的目标文件组成注意,对库的命名要遵循libx.a的原则,其中,x是指定的库名。如本例中,x就是game生成静态库以后,就可在编译C语言源文件时指明对它进行搜索、连接例如:$gccf1.cf2.cf3.c-omygame-static-L$HOME/lib–lgame静态连接效率不高,需占用较多的磁盘空间和内存。利用动态连接可克服上述缺点。进行动态连接的核心问题是生成动态链接库6.2gdb程序调试工具查找程序中的错误,诊断其准确位置,并予以改正,这就是程序调试。程序中的错误按性质可分为三种:①编译错误,即语法错误②运行错误,如除数为0③逻辑错误,程序能运行但结果不对gdb是GNU开发组织发布的一个功能强大的、在UNIX/Linux操作系统上使用的C/C++和汇编语言程序的调试工具gdb主要帮助用户在调试程序时完成4方面工作:①启动程序,按用户要求影响程序的运行行为。②使运行程序在指定条件处停止。③当程序停止时,用户可检查程序出现的问题④动态改变程序的执行环境6.2.1启动gdb和查看内部命令为发挥gdb的全部功能,需要在编译源程序时使用-g选项$gcc-gprog.c-oprog(针对C语言源程序)$gcc-gprogram.cpp-oprogram(针对C++源程序)启动gdb的方法有4种:①直接使用shell命令gdb:$gdb②以一个可执行程序作为gdb的参数:$gdbprgm

prgm是要调试的可执行文件名。③同时以可执行程序和core文件作为gdb的参数。$gdbprgmcore

core文件是直接运行prgm程序造成coredumped后产生的文件。④指定一个进程号PID作为gdb的第二个参数。$gdbprgm12341234是正在运行进程的编号。这样,就把gdb和该进程绑在一起一旦启动gdb,就显示gdb提示符:

(gdb)并等待用户输入相应的内部命令退出gdb:quit启动gdb

利用helpclass命令可以列出指定类class中所包含的全部命令及其功能也可以直接用helpcommand方式来查看指定的command命令帮助信息files类中的命令6.2.2显示源程序和数据1.显示和搜索源程序(1)显示源文件利用list命令可以显示源文件中指定的函数或代码行表6-6

list命令的格式及功能格

式功

能list没有参数,显示当前行周围的10行代码list-显示当前行之前的10行代码list[file:]num显示源文件file中指定行号num周围的10行代码。若省略file,则默认使用当前文件。例如,list100liststart,end显示从行号start至end之间的代码行。例如,list20,

38list[file:]function显示源文件file中指定函数function()的代码行。若省略file,则默认使用当前文件。例如,listmeng1.c:square(2)模式搜索格

式功

能forward-searchregexp从列出的最后一行开始向前搜索给定的模式regexp(即正则表达式,一个字符串的匹配模式)。例如,forward-searchi=*searchregexp同上reverse-searchregexp从列出的最后一行开始向后搜索给定的模式regexp(即正则表达式,一个字符串的匹配模式)。例如,reverse-searchi=??2.查看运行时数据

(1)print命令一般使用格式是:print[/fmt]

exp当被调试的程序停止时,可以用print命令(简写为p)或同义命令inspect来查看当前程序中运行的数据。(2)gdb支持的运算符①用&运算符取出变量在内存中的地址。如:print&i,print&array[i]

②{type}adrexp

表示一个数据类型为type、存放地址为adrexp的数据。③@它是一个与数组有关的双目运算符

如:printarray@10,printarray[3]@5

④file::var

或者function::var

表示文件file(或函数function)中变量var的值。

如:printinner::i(3)输出格式在print/fmt

exp命令中,“/”之后的fmt是表示输出格式的字母,它由表示格式的字母和表示数据长度的字母组成。表6-8

gdb输出格式类

型字

母作

用字

母作

用表示格式的字母o八进制格式f浮点数格式x十六进制格式a地址格式d十进制格式i指令格式u无符号十进制格式c字符格式t二进制格式s字符串格式表示长度的字母b1字节长度h半个字长度w1个整字长度g8字节长度(4)whatis命令显示出变量的数据类型(5)x命令可以查看内存地址中数据的值。其使用格式是:

x[/fmt]

address(6)display命令可以预先设置一些要显示的表达式。

其一般格式是:display[/fmt]

exp

要取消对先前设置的某些表达式的自动显示功能,可以使用命令:

undisplay[disnum]deletedisplay[disnum](7)显示函数调用栈信息

表6-9

显示函数调用栈信息的命令命

令功

能backtrace[n|-n]打印当前函数调用栈的所有信息。若指定参数n(正整数),则仅打印栈顶上n层帧的信息;若参数为-n形式,则仅打印栈底n层帧的信息bt[n|-n]where[n|-n]frame[n]其中,n是栈中帧的编号,从0(表示栈顶)开始递增。若指定参数,则显示当前栈帧的信息;若指定参数n,则将帧号为n的帧设置为当前帧f[n]up[n]向上移动n层栈帧。若不指定参数,则表示向上移动一层down[n]向下移动n层栈帧。若不指定参数,则表示向下移动一层infoframe显示当前栈帧的所有信息,如函数地址、调用函数的地址、被调用函数的地址、当前函数的编程语言、函数参数地址及值、局部变量的地址等infof6.2.3修改和显示目录或路径

(1)directory命令,一般格式是:

directory[dir]

或者dir[dir](2)cd命令,使用格式为:cddir(3)path命令,使用格式是:pathdirs(4)pwd命令:显示工作目录(5)showdirectories:显示定义的源文件搜索路径(6)showpaths:显示当前查找目标文件的搜索路径6.2.4控制程序的执行断点(breakpoint),观察点(watchpoint),捕捉点(catchpoint)它们统称为停止点1.设置和显示断点(1)设置断点:用break命令(缩写为b)设置断点,有7种方法:breaklinenum

breaklinenumifcondition

breakfunction

breakfile:linenumbreakfile:function

break*address

break(2)显示断点infobreakpoints[num]infobreak[num]2.设置和显示观察点(1)设置观察点watchexpr

rwatchexpr

awatchexpr

(2)显示观察点

infobreakpointsinfowatchpoints3.设置捕捉点命令catch的格式是:catcheventevent表示事件。event可以是以下具体内容:signal表示所有信号。signalsignum表示一个特定信号signum。throw表示被抛出的所有异常。catch表示被捕捉到的所有异常。start表示任何刚创建的进程。exit表示任何被终止的进程。load表示载入任何库。unload表示卸载任何库。另一个命令是tcatchevent

(用于设置临时捕捉点)4.维护停止点命

令功

能delete[bkptnums]bkptnums是断点号码。如果要删除多个断点,则各个号码间用空格分开。如果delete命令后面不带参数,则删除所有的断点。其简写命令为dclear清除所有已定义的停止点clearfunctionclearfile:function清除在函数function开头设置的所有停止点clearlinenumclearfile:linenum清除在指定行linenum上设置的所有停止点clear*address清除在指定地址address处设置的所有停止点disable[bkptnums]停用指定的断点,bkptnums是断点号码。如果要停用多个断点,则各个号码间用空格分开。如果命令后面不带参数,则停用所有的断点。其简写命令为disenable[bkptnums]激活被停用的断点,各个断点号码间用空格分开5.运行程序run命令的格式:run[args]args是传给被调试程序的命令行参数。args可以包含“*”、“[…]”等通配符。在命令行上可以使用输入/输出重定向符。如果run命令没有指定实参,gdb将使用最近一次执行调试程序时给它提供的实参6.程序的单步跟踪和连续执行(1)单步跟踪实行单步跟踪的命令是step和next,其格式是:

step[N]N代表每步执行的行数,可进入函数内部执行next[N]

函数调用当做一条指令对待(2)连续执行

continue,c或fg命令连续执行到下一个断点或程序结束7.函数调用

callexpr

执行函数或过程

return[expr]

从正在执行的函数中退出6.2.5其他常用命令1.执行shell命令其格式是:shellcommand-string

例如:

(gdb)shelldate2024年06月21日

星期五10:22:48CST(gdb)2.修改变量值:动态更改被调试程序的运行线路或变量的值

(gdb)printx=10(gdb)setvariablex=103.跳转执行

jumplinenumjump*addr

6.2.6应用示例

示例程序源代码(1)使用带-g选项的gcc命令对该程序进行编译,然后运行:$gcc-gdbme.c-odbme$./dbme***stacksmashingdetected***:terminated已放弃(核心已转储)(2)编译时加入“-fno-stack-protection”选项,随后以程序名dbme作为参数启动gdb。(3)在gdb环境下使用run命令运行该程序

(4)为了了解代码中可能出错的行,使用list命令显示第1~25行的内容(其实该程序只有22行):

(gdb)list1,25(5)设置断点,让程序在文件dbme.c的第21行停止执行,然后运行该程序。

(6)利用print命令可以打印任何合法表达式的值。

(7)查看数组fary元素地址的情况

再查看ary数组后面12个元素的数值。

把源程序中BIGNUM的宏扩展值改为10,重新编译、运行,检查结果正确

6.3make程序维护工具

6.3.1make的工作机制GNU的make的工作过程如下:①依次读入各makefile文件;②初始化文件中的变量;③推导隐式规则,并分析所有规则;④为所有的目标文件创建依赖关系链;⑤根据依赖关系和时间数据,确定哪些目标文件要重新生成;⑥执行相应的生成命令。1.makefile文件make被调用后会依次查找名为GNUmakefile,makefile和Makefile的描述文件一个示例:prog:x.oy.oz.oassmb.ogccx.oy.oz.oassmb.o-L/home/mqc/lib-lm-oprogx.o:x.cdefs.hgcc-cx.cy.o:y.cdefs.hgcc-cy.cz.o:z.cgcc-cz.cassmb.o:assmb.sas-oassmb.oassmb.sclean:rmprog*.omakefile规则有以下通用形式:目标文件:[相依文件…]<tab>命令1[#注释]…<tab>命令n[#注释]在格式上应注意:依赖行从一行的开头开始书写各命令行单独占一行,每个命令行的第一个字符必须是制表符<tab>,而不能使用8个空格#号后的内容为注释在依赖行上,目标文件和相依文件之间要用一个或两个冒号分开2.依赖关系图使用make的一个核心问题是确定好各文件之间的依赖关系。一般来说,生成一个目标文件可能有多个不同的途径,根据这些途径能够指定不同的依赖关系。

原始依赖关系图引入中间结果的依赖关系make是依据“关系图深度优先搜索”的算法来核查目标文件及相依文件的修改时间,深度相等时,可由左到右依次进行。适当地引入中间结果,合理地构造依赖关系图,可以省去一部分编译工作量。但并非层次越多越好,要考虑目标文件的生成过程及其所起的作用。

6.3.2变量1.变量定义和引用make的变量(又称做宏定义)一般均由大写字母和数字组成。定义变量的一般格式是:

<变量名>=<字符串>

例如,下面都是合法的变量定义:

OBJECT=x.oy.oz.oLIBES=-lm引用make变量的方式与引用shell变量类似,即:把变量用圆括号括起来,并在前面加上“$”符号。例如:

$(OBJECT)$(LIBES)2.自动变量除了用户定义的变量外,make也可以使用环境变量、自动变量和预定义变量。

make中定义了一些它们的值会因环境的不同而发生改变的变量,被称为自动变量。

表6-11

make的部分自动变量变

名说

明$@表示规则中的目标文件集合$?所有比目标文件更新的依赖文件的集合,文件之间以空格分隔$<规则中的第一个依赖文件名$^规则中所有依赖文件的集合,文件之间以空格分隔$%仅当目标文件是静态库成员时,表示规则中的目标成员名,此时$@表示相应库文件的名称$*若目标文件的扩展名是make所识别的,则$*表示去掉扩展名的目标文件名,但该引用仅在隐含规则中生效3.预定义变量表6-12

常用的make预定义变量类

别变

量说

明归档库AR归档维护程序,默认值是arARFLAGS传给归档维护程序的参数,默认值是rv汇编命令AS汇编程序,默认值是asASFLAGS传给汇编程序的参数,没有默认值C语言编译命令CCC语言编译程序,默认值是ccCPPC语言预处理程序,默认值是cppCFLAGS传给C语言编译程序的参数,没有默认值CPPFLAGS传给C语言预处理程序的参数,没有默认值C++语言编译命令CXXC++语言编译程序,默认值是g++CXXFLAGS传给C

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论