關於SAP ABAP字元變數和字串變數字元個數的一個知識點,和一個血案

i042416發表於2020-05-02

今天是2020年5月2日,五一國際勞動節小長假的第二天。讓我們繼續勞動起來。

使用ABAP strlen函式計算下列這4個字元和字串變數中包含的字元個數。


關於SAP ABAP字元變數和字串變數字元個數的一個知識點,和一個血案


大家先別急著滑動螢幕,先試著自己計算一下,看和標準答案是否有出入。也許大家覺得這些小的知識點沒什麼用,但Jerry馬上會分享一個我實際處理過的客戶incident,正是由於類似這種看似不起眼的小知識點沒有留意,最後影響了專案進展。


關於SAP ABAP字元變數和字串變數字元個數的一個知識點,和一個血案 關於SAP ABAP字元變數和字串變數字元個數的一個知識點,和一個血案 關於SAP ABAP字元變數和字串變數字元個數的一個知識點,和一個血案 關於SAP ABAP字元變數和字串變數字元個數的一個知識點,和一個血案


正確答案,依次是:

  • 2
  • 1
  • 19
  • 17

逐一解釋。

strlen( lv_s ) = 2

整型變數的值,整數1,賦給字串變數lv_s, 這裡發生一個隱式型別轉換。

SAP幫助文件裡宣告,整型變數賦給字串變數時,如果整數為負數,則字串變數末尾為"-";如果整數為正數,則字串變數末尾為空白字元。換言之,當整型變數到字串變數的隱式型別轉換髮生時,字串變數末尾會多出一位,代表賦值源頭的整型數的符號位。


關於SAP ABAP字元變數和字串變數字元個數的一個知識點,和一個血案


lv_s多出來的這個空白字元在偵錯程式裡看得很清楚,2000正是空白字元的16進位制編碼。同時偵錯程式裡也能看到lv_s的字串個數為2.


關於SAP ABAP字元變數和字串變數字元個數的一個知識點,和一個血案


strlen( lv_s2 ) = 1

和前一例相比,lv_s2的複製操作沒有出現隱式型別轉換,而是直接被賦以了一個字元常量,故字元個數為1.

strlen( lv_ss) = 19

lv_ss的型別為SSTRING,實際就是一個CHAR20:


關於SAP ABAP字元變數和字串變數字元個數的一個知識點,和一個血案


在偵錯程式裡,lv_ss有18個前導空白(leading blank)字元,字元"1"和1個尾部空白(trailing blank)字元組成,總共20個字元,偵錯程式裡的Technical Type顯示為C(20).


關於SAP ABAP字元變數和字串變數字元個數的一個知識點,和一個血案


那為什麼strlen(lv_ss)不等於20,而等於19?SAP幫助文件裡給出了答案——SSTRING即CHAR20這種變數,屬於固定長度(fixed length)型別變數。當使用strlen函式計算這種變數的字串個數時,尾部空白字元不應參加計數,所以要減一。


關於SAP ABAP字元變數和字串變數字元個數的一個知識點,和一個血案


strlen( lv_s3) = 17

有了例三的基礎,這個就很容易了。變數lv_s3型別是CHAR18,屬於固定長度型別變數,因此strlen計算出的字串個數為18 - 1 = 17.

第一個例子中,我們把一個整數直接賦給了一個字串變數,發生了隱式型別轉換。在實際專案中,這種隱式型別轉換很容易出現在函式或者ABAP類方法的引數傳遞中。對於函式或ABAP類方法的形式引數,如果我們傳遞的實際引數型別和其型別不匹配,就會發生隱式型別轉換,這種自動轉換有時並非我們期望發生的,甚至容易被忽略。

看一個真實的例子。我曾經擔任過一個俄羅斯的SAP CRM客戶專案的Dev Angel,收到過一個效能相關的incident,客戶開啟某個UI的速度極其緩慢,甚至經常超時。

我透過除錯,最終發現罪魁禍首位於下段程式碼。該程式碼從SAP CRM發起RFC呼叫,去SAP ERP讀取資料,Max Hit設定為15,意思是期望ERP端至多返回15條記錄。


關於SAP ABAP字元變數和字串變數字元個數的一個知識點,和一個血案


然而從ERP端返回了總共408093條記錄。顯然,雖然透過硬編碼指定Max Hit為15,卻完全沒有起到限制作用。


關於SAP ABAP字元變數和字串變數字元個數的一個知識點,和一個血案


起初我想當然地認為這是ERP函式的bug,沒有正確處理CRM呼叫端傳遞過來的Max Hit. 然而當我在偵錯程式裡單步執行到CRM函式內部檢視iv_max_entries時,一下傻了眼:


關於SAP ABAP字元變數和字串變數字元個數的一個知識點,和一個血案


它的值從15一下變成了3473457. 這個數字是什麼鬼?!

再看函式的形式引數定義,iv_max_entries型別為整型,而二次開發顧問傳入的硬編碼值'15', 是一個字元值,我頓時恍然大悟。


關於SAP ABAP字元變數和字串變數字元個數的一個知識點,和一個血案


'15'是怎麼變成魔幻數字3473457的?

Jerry先不解釋,而是請大家看下面這段程式碼:


關於SAP ABAP字元變數和字串變數字元個數的一個知識點,和一個血案


執行,正好輸出3473457這個魔幻數字。那麼程式碼第四行31003500是哪裡來的?其實就是字串'15'的十六進位制編碼。


關於SAP ABAP字元變數和字串變數字元個數的一個知識點,和一個血案


也就是說,二次開發顧問在RFC呼叫時,將硬編碼的'15'傳給了接受整型變數的函式引數IV_MAX_ENTRIES. 應該該引數型別為整型,所以'15'的十六進位制編碼'31003500'被自動轉換成了對應的整型數3473457. 顯然這不是開發顧問期望的行為,但因為程式能夠繼續執行,所以這個問題暫時被掩蓋了。

而RFC呼叫完成之後,緊接著是一個巢狀的LOOP. 在Max Hit能按照期望工作的前提下,對於最多包含15條記錄的內表,就算進行巢狀的LOOP操作也能很快完成。但如今因為Max Hit不工作,內表記錄從最多15條一下子變成了超過40萬條,在這麼龐大規模的內表上進行巢狀LOOP操作,效能可想而知。

經歷過這次incident的處理之後,我個人覺得,使用隱式型別轉換的最佳實踐就是根本不去用它。程式設計師在工作的時候,必須時刻清醒地知道自己在做什麼,要扼住編譯器的咽喉,而不要被編譯器扼住了咽喉。


關於SAP ABAP字元變數和字串變數字元個數的一個知識點,和一個血案


感謝閱讀,祝大家五一節快樂。

要獲取更多Jerry的原創文章,請關注公眾號"汪子熙":

關於SAP ABAP字元變數和字串變數字元個數的一個知識點,和一個血案


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/24475491/viewspace-2689685/,如需轉載,請註明出處,否則將追究法律責任。

相關文章