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

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

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

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




正確答案,依次是:

  • 2
  • 1
  • 19
  • 17

逐一解釋。

strlen( lv_s ) = 2

整型變量的值,整數1,賦給字符串變量lv_s, 這裏發生一個隱式類型轉換。

SAP幫助文檔裏聲明,整型變量賦給字符串變量時,如果整數爲負數,則字符串變量末尾爲"-";如果整數爲正數,則字符串變量末尾爲空白字符。換言之,當整型變量到字符串變量的隱式類型轉換髮生時,字符串變量末尾會多出一位,代表賦值源頭的整型數的符號位。

lv_s多出來的這個空白字符在調試器裏看得很清楚,2000正是空白字符的16進制編碼。同時調試器裏也能看到lv_s的字符串個數爲2.

strlen( lv_s2 ) = 1

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

strlen( lv_ss) = 19

lv_ss的類型爲SSTRING,實際就是一個CHAR20:

在調試器裏,lv_ss有18個前導空白(leading blank)字符,字符"1"和1個尾部空白(trailing blank)字符組成,總共20個字符,調試器裏的Technical Type顯示爲C(20).

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

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條記錄。

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

起初我想當然地認爲這是ERP函數的bug,沒有正確處理CRM調用端傳遞過來的Max Hit. 然而當我在調試器裏單步執行到CRM函數內部查看iv_max_entries時,一下傻了眼:

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

再看函數的形式參數定義,iv_max_entries類型爲整型,而二次開發顧問傳入的硬編碼值’15’, 是一個字符值,我頓時恍然大悟。

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

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

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

也就是說,二次開發顧問在RFC調用時,將硬編碼的’15’傳給了接受整型變量的函數參數IV_MAX_ENTRIES. 應該該參數類型爲整型,所以’15’的十六進制編碼’31003500’被自動轉換成了對應的整型數3473457. 顯然這不是開發顧問期望的行爲,但因爲程序能夠繼續運行,所以這個問題暫時被掩蓋了。

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

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

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

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章