IBM Support

浅析IBM i上C/C++应用程序编译调试方法

Technical Blog Post


Abstract

浅析IBM i上C/C++应用程序编译调试方法

Body

     软件调试对于编程人员来说有着非常重要的意义,应用程序功能的开发和完善是在不断调试中完成的。本文围绕IBM i上C/C++语言的编译调试问题进行分析和介绍。主要介绍两方面的内容:一是system i上C/C++源程序编译方法,二是C/C++程序在system i上的调试方法。IBM i上编辑应用程序代码可以选择绿屏或者其他平台编辑后上传的方式,这里采用windows 端自选编辑器编辑示例程序test.c,然后通过FTP将源文件传输到system i上编译调试的方式。假设已通过此方式将C的源文件bubbleSort.c、bubbleFun.c、bubbleMain.c上传到目录/myApp下。
一 C/C++源程序编译方法
     System i上编译C/C++应用程序采用ILE的程序模型,源文件首先被编译成MODULE对象,Module对象可以连接生成PGM对象和SRVPGM对象。为便于理解,可以将Windows平台的obi、exe、dll类型对照到IBM i的MODULE、PGM、SRVPGM对象。这里需要注意,一个PGM可以链接一个或者多个MODULE和SRVPGM,一个SRVPGM同样可以链接多个MODULE和不同的SRVPGM。下面首先介绍MODULE的创建方法,然后根据生成的MODULE介绍如何创建PGM和SRVPGM。在介绍创建MODULE、PGM、SRVPGM详细步骤中,仅对本文涉及到的参数项进行解释说明,其他选项的详细信息可参阅IBM info center。
 创建MODULE
a)绿屏命令行下输入“CRTCMOD”,按F4提示功能键。准备调用ILE C编译器。
     MODULE:待编译源文件生成的目标MODULE名。
     Library:生成的MODULE放置的目标库名。
     Source stream file:源代码所在的IFS路径。填写源文件的位置时可以采用IFS文件路径或QSYS.LIB MBR文件的方式(须填写Source file、library和Source member),本例采用文件IFS路径。
     Text 'description': 该MODULE的描述信息(非必填信息)。
     本例中上述选项所填的信息如下图所示,其中APP为系统中之前创建的library。    
图像 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b) 按F10 → PageDown功能键。
     Output options: 表示是否产生相应的编译listing结果信息,该信息可显示编译的选项设置、过程和结果用以更正程序语法错误。选择*PRINT代表在SPOOL FILE中生成编译信息,通过WRKSPLF命令查看该文件。
     Title: 生成的listing文件的主标题,最大80字符。用于标识生成的文件。
     Subtitle: 生成的listing文件的副标题,最大80字符。
     本例中上述选项所填信息如下图所示: 图像 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c)按PageDown功能键。
     Debugging view:控制如何编译带有调试信息的程序,*SOURCE表示编译生成的调试信息中带有源代码的路径,调试时可以自动找到并显示源代码,但源代码的路径在编译后不可以移到其他地方。*STMT表示生成的调试信息中不包含源代码的位置信息,但包含源程序语句序号的信息。用户可以根据过程名和语句编号来设置断点。*LIST表示编译生成的调试信息中包含完整的源代码清单,编译完成后,该源代码清单与源程序文件没有直接关系,属于不同的副本,故源代码的路径可以更改。其编译出的程序源代码尺寸较前两种大。此处我们填写为*ALL,同时生成前面三种调试信息。
     本例中Debugging view 填写*ALL, 未涉及的选项标签在本例中为默认设置。
d)正确填写以上信息后按回车键。
若源代码书写正确编译成功,将在所填写的库位置产生相应的带有debug信息的TESTMODULE *MODULE对象。若编译出错,可到spool File中查找BUBBLE文件根据错误的提示修改源码,重复上述编译步骤。
 创建PGM
应用上面生成的MODULE BUBBLE对象创建PGM方法如下:
a) 绿屏命令行下输入CRTPGM,按F4提示功能键。
     Program: 待生成的PGM名。
     Library: 生成的程序所放置的目标位置库名。
     Module: 生成该PGM所需要的MODULE,可以填写一个或多个MODULE。
     Library : 所添MODULE的位置库名。
     Text 'description':待生成的PGM的描述信息。
     本例中上述选项所填信息如下图所示: 
图像 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b)按F10 → PageDown功能键。
     此处介绍下Bind service program相关选项,当绑定 SRVPGM时需要填写下面信息。
     Service program:绑定的SRVPGM名字。
     Library:绑定的SRVPGM所在的库。
     Activation:激活服务程序的方式。*IMMED代表调用应用程序时立即激活服
务程序,*DEFER表示当应用程序调用到服务程序导出的过程时再加载。我们生成的第一个PGM中不包含SRVPGM,上述信息不填,采用默认值。后文调试SRVPGM时,需要自行创建绑定有待调试SRVPGM的PGM。c++源文件生成MODULE的命令是CRTCPPMOD,生成PGM命令仍为CRTPGM。
 创建SRVPGM
     System i上ILE SRVPGM不能独立运行,但可以被其他SRVPGM和PGM调用。一般创建SRVPGM所需的MODULE对象的源文件不包含main()函数。创建SRVPGM前首先创建MODULE,命名为BUBBLESRV,方法与前文介绍的相同,注意开启DEBUG参数。接下来在绿屏下输入CRTSRVPGM,按F4提示功能键。
     Service program:待生成的目标SRVPGM名称。
     Library: 待生成的SRVPGM所在的库名字。
     Module:生成该SRVPGM所链接的MODULE名字。一个SRVPGM可以链接一个或多个MODULE。
     Library:被链接的MODULE所在的库名字。
     Export: 标识此SRVPGM导出的函数或者数据。可以通过源文件标识特定的导出函数或者数据,此时需要填写Export source file,Library,Export source member。也可以填写*ALL,表示MODULE中导出的的所有函数和数据在生成的SRVPGM中也将全部导出。
     本例中上述选项所填信息如下图所示: 
图像
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
二 C/C++绿屏调试方法
     下面介绍IBM I 上C/C++应用程序绿屏环境下的调试方法。调试方法可以按照调试过程中JOB的个数简单分为两种类型,单job调试和两个job之间联合调试。所谓单job调试是指被调试的PGM对象在当前的JOB中运行和调试。所谓两个job之间联调是指被调试的PGM对象在当前job中调试,但在另外一个job中运行。通过启动特定的服务job监控调用被调试PGM的job,服务job负责绑定并触发绿屏调试界面。下面分别进行阐述。
 IBM i绿屏下单job调试
     在一个job中调试PGM是C/C++应用程序调试的最简单情况,它的基本原理可以概括为:启动待调试的PGM源码 → 在源码上设置断点 → 退出源码界面 → 触发待调试的PGM → 调试 → 关闭。详细步骤如下:
a) 启动待调试PGM。
    绿屏命令行下执行“STRDBG APP/BUBBLE”启动待调试的PGM源码(BUBBLE为上文生成
的PGM对象),源代码调试界面如图所示: 
图像 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b)设置断点/条件断点。
     可以通过命令行或功能键设置断点。如br 25将在25行设置断点;br 25 when value=1 将设置条件断点;按功能键F6将在鼠标当前所在行设置断点,断点行以白色显示。断点设置完成后按F12返回。此处我们在行Test.c的第11行设置断点命令br 11。
c) 触发待调试程序。
     如何触发已设断点的待调试应用程序是调试的关键步骤,本例相对比较容易,直接执行CL command:“CALL APP/BUBBLE”,待调试程序将被触发并停止在之前所设置的11行断点处,当前运行以白色显示。将如图所示。图像 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

d) 调试程序。此时仍然有命令行和功能键两种方式控制debug程序的执行。如F10单步执行, F11显示光标所在处变量的值。其调试方法和技巧与其他平台类似。可以在绿屏命令行下执行”HELP“命令查询具体的命令的使用方法。此处我们单步执行,按F10程序执行一行如图所示:图像 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

快捷键对应的命令可以参照下表:

功能

快捷键

命令

显示所有支持的Debug命令

F1

HELP

光标当前行设置为断点

F6

BREAK

单步执行,跳过函数。

F10

STEP

显示光标所在处变量的值

F11

EVAL

运行到下一个断点

F12

NEXT

查看当前模块的所有断点

F13

NO

查看module列表

F14

NO

切换视图模式

F15

NO

查看调用栈

F21

NO

单步执行,进入函数内部

F22

STEP INTO

查看输出窗口

F23

WATCH

 
调试程序可以反复修改并调用call命令触发调试,也可以通过F14功能键添加更多的调试程序。需要注意的是STRDBG命令只能成功执行一次,即针对一个调试程序有效,对程序成功调试之后需调用ENDDBG命令结束程序调试,否则无法调试下一个不同的程序。
 IBM i绿屏下两个Job联合调试
     上面的调试属于在一个job内完成调试工作,但在实际应用中很多待调试程序以服务程序对象SRVPGM方式存在所以如何调用SRVPGM、如何触发DEBUG调试器是调试SRVPGM的关键。IBM i上利用服务JOB来调试ILE程序或者ILE服务程序,调试器和被调试程序将位于不同的JOB中,即两个job间联合调试。其基本原理是:作为服务job B连接到job A,服务job B负责设置断点和调试程序。而调试程序的触发则是在job A中完成的。详细的调试步骤为:
a)编译带有调试信息的ILE服务程序。
    创建MODULE:CRTCMOD MODULE(APP/SRVMOD)
    SRCSTMF('/myApp/bubbleFun.c') OUTPUT(*PRINT) DBGVIEW(*ALL)
    创建SRVPGM:CRTSRVPGM SRVPGM(APP/SRV)
    MODULE(APP/SRVMOD) EXPORT(*ALL) 
 b) 编译带有调试信息的调用ILE服务程序的PGM。
    创建MODULE:CRTCMOD MODULE(APP/SRVP) SRCSTMF('/myApp/bubbleMain.c') OUTPUT(*PRINT) DBGVIEW(*ALL)
    创建PGM:CRTPGM PGM(APP/BUBBLEMAIN) MODULE(APP/SRVP) BNDSRVPGM((APP/SRV *IMMED))
c) 启动绿屏终端A,A中将会触发调试的服务程序。
d) 启动另一个绿屏终端B,在终端B中通过STRSRVJOB命令来捕获终端A中触发的服务程序。该命令有Job name、User、Number三个参数需要填写,代表需要被监控的终端A上的作业。终端A上shift+ESC回车,选择3,即可显示A上终端作业,如图:
图像 
 
 
 
 
 
STRSRVJOB的填写信息如下:图像 
 
 
 
 
 
 
 
e) 在终端B中,使用STRDBG SRVPGM(LCF/SRV) 命令将被调试的ILE服务程序置于调试模式并按上文介绍的方法设置断点在第六行,如图所示: 图像  
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f) 在终端A中启动一个作业,在该作业中调用被调试的ILE服务程序,此过程是单Job调试方式中的debug触发,执行CALL LCF/ TESTMAIN。

g) 当终端A中的作业调用到ILE服务程序提供的某个过程时,终端B将自动显示调试界面,并且程序将停止在上文在A终端设置的断点处。如图所示: 
图像 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
h) 在终端B中,利用上文介绍的PGM对应的调试命令进行调试。
i) 调试结束后,终端B中按下F3或者F12功能键退出调试器。在终端B中,命令行下执行“ENDDBG”退出调试模式。在终端B中,命令行下执行“ENDSRVJOB”,结束终端B对终端A中作业的调试。
     以上介绍了System i上C/C++应用程序绿屏编译调试MODULE、PGM、SRVPGM的基本方法,在实际应用中,应用程序的编译还需考虑很多因素。由于篇幅所限,很多详细的编译选项未全部阐述,读者可以根据上述编译命令查阅相关文档自行尝试。绿屏调试是system i调试的一种方式,GUI方式调试具有更好的人机交互界面,有兴趣的读者可以尝试。
 
 
作者:李长锋,王大炜,王定国
 
 

[{"Business Unit":{"code":"BU058","label":"IBM Infrastructure w\/TPS"},"Product":{"code":"SWG60","label":"IBM i"},"Component":"","Platform":[{"code":"PF025","label":"Platform Independent"}],"Version":"","Edition":"","Line of Business":{"code":"LOB57","label":"Power"}}]

UID

ibm11145428