分享一个 Debug 过程

作者:SAPTAB 约 9 分钟阅读 更新日期:2025-03-02 1 年前更新 标签:ABAP, Data Engineering, PP, SD, 开发, 数据工程, 生产, 销售分销
分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图

原创 Tab Zhu [ SAP TAB ](javascript:void\(0\);)

ABAP 业务Debug 之前写过一篇 [ debug的简单操作

](https://mp.weixin.qq.com/s?__biz=MzUxODI4MTQyMg==&mid=2247483738&idx=1&sn=accb99d6355f0ffa9dd85131298c6516&chksm=f98a00fbcefd89ed5243c6c78a9fac3a00a2a5569a4ee58c9c3656d32cb33ee71f7ddd03f817&token=1362387291&lang=zh_CN&scene=21#wechat_redirect)

,讲述的是如何去debug,今天写一下如何根据具体的业务报错,来一步步找到问题所在

在E-invoice 功能中,在点击display->Preview XML,系统会进行报错,提示的是街道名称不存在

分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图

但是其对应的用户地址已有street的内容维护了,让我们看下为啥程序还是报这个错误

分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图

一般对于这种报Message的错误,我们会直接按照 [ ABAP随便-简单Debug

](https://mp.weixin.qq.com/s?__biz=MzUxODI4MTQyMg==&mid=2247483738&idx=1&sn=accb99d6355f0ffa9dd85131298c6516&chksm=f98a00fbcefd89ed5243c6c78a9fac3a00a2a5569a4ee58c9c3656d32cb33ee71f7ddd03f817&token=1362387291&lang=zh_CN&scene=21#wechat_redirect)

中描述的消息断点进行debug 首先我们双击一下这个Message Text来确定这个message的ID和Number为EDOCUMENT_IT(007)

分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图

我们在 **EDOC_COCKPIT** 初始界面,输入invoice之后,在左上方搜索栏中输入/H,然后点击display

分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图

这时我们会进入debug界面:点击F9,然后点击消息/Message页签,输入我们刚才的消息号点击回车确认

分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图

然后我们点击F8,直接执行,这个时候会直接结束debug返回EDOC_COCKPIT初始界面,我们再次点击Display->Display/Preview

XML

分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图

然后系统会自动在Message触发的地方展现Debug界面

分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图

我们会发现是这个变量<ls_fattura>-fattura_elettronica_header-cessionario_committente-

sede-indirizzo为空,所以导致的错误message的抛出

根据12行的代码,我们可以知道这个<ls_fattura>是从外部传进这个类的;所以我们先点击下F7(跳出当前的方法),这时我们看到is_out_struct也是从外部传入

分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图

同理 我们再点击F7跳出这个方法:

分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图

我们这时可以看到out_struct,可以得出<ls_fattura>-fattura_elettronica_header-

cessionario_committente-sede-indirizzo

这个值一定是在这之前赋值的,其实debug的思路就是从message出发,一步一步向前找到indirizzo赋值的地方,而且其中有很多的地方需要大胆推测小心求证(连蒙带猜)。比如当前的function

moudule的名称是EDOC_AIF_GENERIC_CHECK,所我们认为这个函数大概率只是检查数据,所以我们再点F7跳出函数,然后我们可以看到进入了函数/AIF/FILE_TRANSFORM_DATA中

分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图

在代码处点击右击选择Goto Source Code,这时会弹出一个新的GUI界面显示函数/AIF/FILE_TRANSFORM_DATA,

分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图

然后我们在弹出的界面中双击OUT_STRUCT变量,然后到跳到该函数输入输出的地方:

分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图

我们可以看到这是一个输出变量,那么我们需要的<ls_fattura>-fattura_elettronica_header-

cessionario_committente-sede-indirizzo

一定是在这个函数中赋值的,我们Ctrl+F从上到下搜索一下OUT_STRUCT

分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图

然后我们可以看到在548行的地方调用了一个函数,其中OUT_STRUCT为Changing变量,由上方542行注释也可以判断出,这里应该是将RAW_STRUCT数据放置到OUT_STRUCT中的一个作用。又由于548行的ls_finf-

fuba_init_trans是一个变量,所以我们返回到Debug界面,双击一下该行变量,我们即可在右侧变量栏位中看到函数的名称为:EDOC_AIF_INIT_REQUEST_MAPPING

(使用Desktop 3页签)

分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图

所以我们在另一个GUI界面SE37看一下这个函数:OUT_STRUCT实参对应函数的形参是DATA

分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图

然后我们可以在这个函数中看到Data变量在98行作为cl_edoc_map_aif=>map_interface这个方法的输出实参

分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图

同理,我们继续进一步在cl_edoc_map_aif=>map_interface中找到做为es_target的形参在77行和84行进行了输出

分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图

由于这个是变量,而我们刚才又debug到该代码后面去了,所以我们需要在这个方法cl_edoc_map_aif=>map_interface中打个断点,然后重新执行GUI上的功能:

分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图

当我们程序停在这个断点(71行)的时候,我们按下F5,我们可以看到接下来执行的类是:CL_EDOC_MAP_IT_SD 方法为:MAP_INVOUT2

分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图

所以我们在另一个GUI界面查看这个类方法:

分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图

我们可以从最后的54行的语句中看到类全局变量ms_target_121赋值给了es_target,说明我们所需要的indirizzo

是在这个类中赋值的,但是这个类中掉了一堆的方法,如init_mapping(),fill_fattura_header_121(),fill_fattura_body_121()等都可以能对indirizzo进行赋值,那要如何去定位呢?

所以我这里找了一个正确的invoice去跑,发现ms_target_121-fattura_elettronica_header-

cessionario_committente-sede-indirizzo 在执行fill_fattura_header_121()方法时进行了赋值

分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图

所以我们在另一个GUI窗口中双击fill_fattura_header_121()进行查看:幸运的是,我看到了fill_cessionario_committ_121(

),看名称和结构中的cessionario_committente很相似,所以大胆点进去看

分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图

果然,我们在fill_cc_sede_121( )中看到了indirizzo的赋值 = ms_source-addr_customer-street.

分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图

所以我继续找ms_source-addr_customer-

street的赋值再何处,其实已经可以猜到了,肯定在CL_EDOC_MAP_IT_SD->MAP_INVOUT2方法的init_mapping(

)方法中,根据正确的invoice的debug我们也可以看出:在执行完init_mapping( )之后,ms_source-addr_customer-

street有值了 所以我们继续查看init_mapping( )这个方法:通过正确的invoice查看,我们可以确定在方法init_mapping(

)中的函数EDOC_IT_FATTURAFI_INIT_MAPPING完成了ms_source-addr_customer-

street的赋值:我们查看该函数中99行EDOC_IT_GET_CUSTOMER_ADDRESS函数和322行 MOVE-CORRESPONDING

ls_adrc_cust TO ls_raw-addr_customer的赋值语句

分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图

我们可以知道street就是通过这2处来赋值的,所以我们去debug那个错误的INVOICE,这是发现在函数EDOC_IT_GET_CUSTOMER_ADDRESS的输出实参中LS_ADRC_CUST-

STREET是有值的

分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图

然后我们继续往下执行,发现在该函数173行除直接退出了,所以造成了没有street的赋值,进而引发了后面一系列的报错

分享一个 Debug 过程 - 封面图
分享一个 Debug 过程 - 封面图

至此,该问题已经debug完成。

总结下:其实Debug的过程是一种类似推理的过程,说简单也简单,说难也难,很多时候需要猜测和根据经验判断,先根据一个message的报错消息,定位到消息出发的地方,然后根据其出发的条件,不断向前面的代码打上断点来一次次Debug。

SAPTAB

关于作者:SAPTAB

企业信息化与 SAP 技术顾问,长期专注 SAP ABAP、FI/CO、MM、SD 等模块的技术分享与实战经验总结。查看更多介绍

来源说明:本文内容由「分享一个Debug过程.md」整理生成,仅用于内部技术分享与学习交流。