实验五常用软件开发工具.docx

上传人:b****6 文档编号:7338279 上传时间:2023-01-23 格式:DOCX 页数:19 大小:19.88KB
下载 相关 举报
实验五常用软件开发工具.docx_第1页
第1页 / 共19页
实验五常用软件开发工具.docx_第2页
第2页 / 共19页
实验五常用软件开发工具.docx_第3页
第3页 / 共19页
实验五常用软件开发工具.docx_第4页
第4页 / 共19页
实验五常用软件开发工具.docx_第5页
第5页 / 共19页
点击查看更多>>
下载资源
资源描述

实验五常用软件开发工具.docx

《实验五常用软件开发工具.docx》由会员分享,可在线阅读,更多相关《实验五常用软件开发工具.docx(19页珍藏版)》请在冰豆网上搜索。

实验五常用软件开发工具.docx

实验五常用软件开发工具

 

实验五、常用软件开发工具

 

一、实验目的

 

1、熟悉字符模式下的C程序编译和调试环境,基本掌握Linux字符模式下的编译工具

 

和调试工具的使用;

 

2、本实验需要综合使用Linux基本文件命令、编辑器的使用,练习在Linux的字符模

 

式下,编辑、编译及调试一个C程序的基本方法。

 

二、实验内容和步骤

 

1gcc和g++语言编译器

 

GCC是GNUCompilerCollection的缩写,它是世界上最为重要的开放源代码软件[18]。

 

因为所有其他的开放源代码项目都依赖于GCC进行编译。

比如,没有GCC,Linux的产生就

 

不会成为可能。

 

GCC能工作在很多平台上,这里所说的平台是指计算机硬件芯片和运行在其上的操作系

 

统的组合。

下表是GCC运行的平台。

 

表GCC运行的平台

 

硬件操作系统

 

AlphaRedHatLinux

 

HPPAHPUX

 

Intelx86DebianLinux,RedHatLinux,FreeBSD

 

MIPSIRIX

 

PowerPCAIX4.3.3

 

SparcSolaris

 

GCC可以编译多种语言:

C,C++,对象C(标准C的派生),Fortran,Java,Ada。

正如GCC

 

缩写所代表的对象一样,GCC实际上是多种编译器的统称,gcc是所有编译器的统一的程序

 

接口,在本书中,并没有区分GCC和gcc。

同时,GCC也能够进行代码优化,提高执行程序

 

的运行速度。

g++是构建于gcc基础上的C++语言编译器。

 

gcc编译过程分为4个阶段:

 

l预处理

 

l编译

 

l汇编

 

l连接

 

最简单的C语言编译的例子:

 

用vi建立一个文件$vi

 

输入字符i,插入文本以下文本

 

/*

 

*

 

*/

 

#include<>

 

intmain(void)

 

{

 

printf("HelloWorld!

\n");

 

return0;

 

}

 

最后输入字符:

wq,返回命令行,键入以下编译命令:

 

$gcc(-lstdc++)

 

如果没有错误gcc将生成默认的可执行文件,执行:

 

$./

 

HelloWorld!

 

$

 

gcc带有多达数页的编译选项,我们仅列出最常用的几项:

 

-o可执行文件名指定输出的可执行文件名,而不是默认的

 

-c只编译生成.o的目标文件,不连接生成可执行文件

 

-s只编译生成.s的汇编文件,不连接生成可执行文件

 

-g在可执行文件中加入标准调试信息

 

-Wall允许GCC发出警告型错误信息

 

选项使用的例子:

 

对以上使用-o,-g常用选项重新编译、执行:

 

$gcc-g-ohello

 

$./hello

 

HelloWorld!

 

$

 

GCC默认的扩展文件名:

 

.c

 

C

 

语言源代码

.C

.cc

C++

语言源代码

.i

预处理后的

C语言源代码

.ii

预处理后的

C++语言源代码

.S.s汇编语言源代码

 

.o编译后的目标代码

 

.a.so编译后的库代码

 

下面的例子由两个文件组成:

,其中,文件内容为:

 

#include<>

 

intcalc(int);

 

intmain(intargc,char*argv[])

 

{

 

intiInput=0,iOutput=0;

 

inti=0;

 

scanf("%i",&iInput);

 

while(iInput<0)

 

{

 

printf("Pleaseinputapositiveinteger!

\n");

 

scanf("%i",&iInput);

 

}

 

iOutput=calc(iInput);

 

printf("Resultis:

%i\n",iOutput);

 

return0;

 

}

 

的文件内容为:

 

#include<>

 

intcalc(intiIn)

 

{

 

inti=0,iOut=0;

 

iOut=iIn;

 

for(i=0;i

 

{

 

iOut+=iOut*iIn;

 

}

 

returniOut;

 

}

 

1、编译过程

 

有三种方式编译这两个源程序,一是直接使用如下命令行完成编译、链接过程:

 

$gcc-omain

 

命令行中,的后缀名指明了调用c编译器,前面讲到了gcc是GCC的众多编译器的统

 

一入口,gcc靠后缀名决定调用什么编译器,-o参数指定了可执行文件的文件名为main。

 

第二种方法是编译为静态库,编译时指定静态库的位置。

 

需要将编译成中间文件,使用如下命令行:

 

$gcc-c

 

生成静态库文件,添加到静态库中,使用如下命令行:

 

$ar-r

 

命令行中,-r参数表示建立静态库,名字为。

 

接下来,使用如下命令行:

 

$gcc-omain

 

上面这条命令也可以用下面的命令完成:

 

$gcc-lcalc–omain

 

-l参数可以指定库名称,这里calc表示使用库,库名字前面的lib和后面的.a被省略

 

掉了,遵从了命名法。

 

第三种方法是建立共享库,编译时指定共享库。

 

首先,编译为,使用命令行:

 

$gcc-c-fpic

 

命令行中,-fpic指定为可重分配地址属性,pic是positionindependencecode的缩

 

写。

 

接下来使用生成共享库:

 

$gcc-shared–o

 

这两条命令也可以缩减为一行:

 

$gcc-shared-fpic-o

 

最后编译,链接生成的共享库:

 

$gcc-omain

 

2make项目管理器

 

make项目管理器(GNU中的名称为gmake)可以根据项目开发者说明的项目开

 

发文件Makefile自动的进行编译配置和重复编译,能实现复杂项目的编译自动化。

 

项目开发文件Makefile的编写使用以下规则:

 

目标体1:

依赖体1[依赖体2[...]]

 

命令行1

 

命令行2

 

[...]

 

目标体2:

依赖体1[依赖体2[...]]

 

命令行1

 

命令行2

 

[...]

 

[...]

 

其中目标体是命令行要生成的输出文件,依赖体是命令行要输入的文件或选项,命

 

令行序列是要创建目标体文件所需要的步骤,例如编译命令。

无特别指定,make

 

总是使用当前目录中的Makefile进行自动编译。

 

例如我们在当前目录中有两个项目开发文件和,则Makefile文件可以

 

编写为:

 

hello:

 

gcc-ohello

 

:

 

gcc-c

 

clean:

 

rmhello*.o

 

make命令的使用:

 

$gmake

 

输入make或makehello将生成Makefile中所有的目标文件,即hello,,。

 

$gmake

 

将仅生成目标文件

 

$gmakeclean

 

是一条伪目标生成命令,该目标没有依赖体,它只执行对已生成目标文件的删除。

当我们对

 

以上依赖体中的任意一个进行了修改,重新make时仅会引发对应目标体的重新生成,从而

 

提高了编译的效率并保证了项目开发的正确性。

 

3gdb程序调试器

 

GDB是GNUProjectDebugger的缩写,用于调试Ada,C,C++,Objective-C,Pascal和

 

其他语言编写的程序[20],这些程序可以运行在本地计算机上,也可以运行在远程计算机上。

 

GDB可以运行在几乎所有的UNIX和微软Windows平台上。

 

GDB主要能做下面4种事(以及由它们所支持的其他事情):

 

1)启动程序,指定可能影响程序运行的任何条件;

 

2)指定程序在一定条件下停止;

 

3)检查当程序停止时发生的事情;

 

4)通过改变程序中的某些条件,测试可能造成的软件错误,还可以由此学习其他的软

 

件错误。

 

GDB可以做源代码级别的程序调试(需要在编译时指定相应条件),也可以做二进制级

 

别的程序调试。

 

如果您在gcc编译选项中用到了-g调试选项,则编译出的可执行文件就会带有符号表。

 

样的程序就可以使用gdb跟踪调试,观察到它的高级语言源代码的执行过程和变量的中间

 

结果,从而能快速的排除程序运行时发生的错误。

以下是一个带有运行时错误的C程序,注

 

意程序想通过传地址方式在一个函数中为字符变量C赋一个字符,但它引用了一个空指针,

 

这将引发运行时的段非法错误使得程序异常终止。

但我们可以通过gdb跟踪到它产生错误

 

的位置,从而分析出产生错误的原因。

 

/*

 

*

 

*/

 

#include<>

 

voidmyputc(char*cptr)

 

{

 

*cptr='a';

 

printf("myputc=%c\n",*cptr);

 

}

 

intmain(void)

 

{

 

charc;

 

char*cptr;

 

c='A';

 

myputc(cptr);

 

return0;

 

}

 

使用带-g选项的gcc编译、执行:

 

$gcc-g-odebugmy

 

$./debugmy

 

段错误

 

$

 

使用gdb跟踪查错

 

$gdb./debugmy

 

GNUgdbRedHatLinux(6.3.0.

 

Copyright2004FreeSoftwareFoundation,Inc.

 

GDBisfreesoftware,coveredbytheGNUGeneralPublicLicense,andyouare

 

welcometochangeitand/ordistributecopiesofitundercertainconditions.

 

Type"showcopying"toseetheconditions.

 

ThereisabsolutelynowarrantyforGDB.Type"showwarranty"fordetails.

 

ThisGDBwasconfiguredas"i386-redhat-linux-gnu"...Usinghost

 

libthread_dblibrary

 

"/lib/".

 

(gdb)

 

现在进入了gdb调试状态,可以使用gdb的调试子命令跟踪程序的执行。

Gdb常

 

用命令:

 

list[行号]列出指定行号的上下行(缺省为10行)

 

break[源程序文件名:

]行号建立一个断点

 

run启动被调试的程序

 

next从断点处向下执行一行

 

step从断点处向下执行一行,当前行为函数则跟踪进入函数

 

continue继续从断点处连续执行

 

print变量名打印变量当前值

 

quit退出gdb

 

让我们现使用list命令查看一下要调试的程序是否已经装入,输入:

 

(gdb)list10

 

5voidmyputc(char*cptr)

 

6{

 

7

*cptr='a';

8

printf("myputc=%c\n",*cptr);

9

}

 

10intmain(void)

 

11{

 

12

charc;

13

char*cptr;

14

c='A';

 

我们将断点设在第15行上,输入:

 

(gdb)break15

 

Breakpoint1at0x80483c0:

file,line15.

 

开始跟踪执行,输入:

 

(gdb)run

 

Startingprogram:

/root/ipc/debugmy

 

Readingsymbolsfromsharedobjectreadfromtargetmemory...done.

 

LoadedsystemsuppliedDSOat0xffffe000

 

Breakpoint1,main()at:

15

 

15myputc(cptr);

 

程序执行到第

 

15行上停止,我们采用单步执行跟踪错误的发生,输入

 

:

(gdb)step

 

myputc(cptr=0x9bbe40"U\211WVS\203L\215s")at:

7

 

7

 

*cptr='a';

程序执行一行,进入函数myputc,再单步执行一行,再次输入:

 

(gdb)step

 

ProgramreceivedsignalSIGSEGV,Segmentationfault.

 

0x0804838dinmyputc(cptr=0x9bbe40"U\211WVS\203L\215s")at:

7

 

7*cptr='a';

 

此时gdb报告在执行改行时接受到一个段失败的信号,由此我们可以知道错误发生在该行

 

上,进一步我们可以推断出该错误的发生是因为指针cptr未初始化,它指向了一个非法的

 

地址,所以在向它指向的单元赋值时发生了段错误。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 研究生入学考试

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1