隱藏極深的空指標

2021-07-30 12:28:07 字數 1163 閱讀 2353

最近測試反饋了乙個bug,經過檢視日誌發現是mq訊息重複消費導致的,一開始連續重試,等重試了一會,後來就變成了每隔兩分鐘重試一次。這應該是mq框架的功能,遇到某種情況,mq框架認為消費者沒有能成功把訊息消費掉,所以一直不斷嘗試,重新消費。

最大的可能就是業務**拋異常了,一路拋給了mq框架,所以mq框架才會如此鬼畜。

但是在專案日誌中完全沒看到異常日誌啊?怎麼回事。

可能正是因為異常一路丟擲去了,在業務**中都沒有catch,因此也沒有列印。

@override

public

void

onmessage(listmessages) throws exception catch (exception e)

}

異常終於打出來了,是空指標異常… 報錯的**行如下:

if (member != null && member.gethasautolevel() == autolevelenum.no.value) {
已經確定 member 不為空了,想了半天都不知道這行**為啥報空指標異常。

hasautolevel 型別為 short,autolevelenum.no.value為int。hasautolevel 的確為空,但這怎麼會導致空指標異常呢,又沒有操作它。

後來發現,這是乙個 short引用型別與int基本型別的 == 比較,編譯器會自動將引用的包裝型別進行拆箱,即呼叫 short.shortvalue(),而hasautolevel 為null,在null上呼叫因此會報空指標!

總結:

1. 此次修復這個bug,耗時幾乎三天,之所以耗時這麼長,最主要的原因是對日誌框架以及異常傳播行為不熟悉。由於業務**中不可能將所有**全部包在try catch(exception)中,因此有些執行時異常(runtimeexception)不能**捉到,因此會沿著方法呼叫鏈一層一層地往上拋,如果最終拋到了乙個第三方框架中,業務層**沒有捕捉到該異常,而專案中配置的日誌收集器並不收集此第三方框架的日誌,那麼專案日誌中便記錄不到此異常資訊。

2. 包裝型別與基本型別進行 == 比較會涉及到自動拆箱,如果包裝型別為null,那麼就會丟擲空指標異常。

3. 消費者在消費mq訊息時,如果把異常拋給mq框架,那麼mq框架會認為訊息沒有成功被消費,因此會一直重試消費,直到將其消費完畢。

空指標的理解

空指標 null pointer 空指標 乙個被賦值為0的指標 1 空指標常量 null pointer constant an integer constant expression with the value 0,or such an expression cast to type void ...

指標的深拷貝

在對指標進行操作時經常會涉及到指標的拷貝,一般來講指標的拷貝分為兩種 深拷貝與淺拷貝。兩者之間使用不當會造成很惡劣的影響。下面例項說明 我們先設定乙個字串指標s,假設其指向記憶體的內容是 adfsdfsf 記該儲存區域為m,那麼我們得知,s指標所指向區域m。若我們的用指標p對其內容進行淺拷貝,那麼我...

空指標和迷途指標的區別

解釋 include int main int pint new int pint 10 cout pint delete pint pint 0 pint 20 oh no,this was deleled.cout pint 迷途指標也叫懸浮指標,失控指標,是對乙個指標delete後 這樣會釋放...