#工作心得 有些 Bug 不是邏輯錯,而是狀態沒有被初始化

|工程師日記 #1 最近遇到一個蠻離奇的問題。 現場在操作某個「物料位置設定」功能時,原本是要把資料設定到 Port A。 結果設定完成後,資料卻出現在 Port B。 這種問題第一眼看到,其實很容易先往幾個方向想: 是不是現場操作錯? 是不是選錯 Port? 是不是物料編號輸入錯? 但後來查下去才發現,事情沒有那麼單純。 因為這個問題不是每次都發生。 有時候正常,有時候異常。 而且異常發生時,從畫面上看,操作流程也不一定會有很明顯的錯誤。 這種才是最麻煩的。 後來是一路追 LOG,再回頭看操作畫面的 source code, 才發現問題出在一個很不起眼的地方。 不是控制邏輯錯。 也不是資料計算公式錯。 而是畫面上的某個下拉選單,沒有在正確時機重新初始化。 程式裡大概是這種概念:PortNo := ComboBox.ItemIndex + 1; 也就是說,程式會拿畫面目前選到的下拉選單 index,再加 1,轉成實際的 Port No. 例如: index = 0,代表 Port 1 index = 1,代表 Port 2 index = 2,代表 Port 3 這個寫法本身不一定有問題。 真正的問題是: 如果前一次操作曾經選過其他 Port,而畫面再次開啟時,這個下拉選單沒有被重新設定成預設值,那它就有可能保留前一次的選擇狀態。 這時候如果現場人員沒有特別重新選一次 Port,程式就會直接拿到上一輪殘留的值。 後面又會把 Port No. 跟物料編號組成一個資料,再送到控制端。 概念大概像這樣:setVal := (PortNo * 100) + materialNo; 所以問題就出現了。 畫面上看起來是在設定 Port A, 但程式實際拿到的 Port No.,可能還停在前一次的 Port B。 最後送出去的資料,自然就會跑到錯的 Port。 這種 Bug 很陰,因為單看每一段程式都很合理。 下拉選單 index 加 1,很合理。 Port No. 加上物料編號組成資料,很合理。 按下按鈕後把資料送出去,也很合理。 但整個流程串起來,卻少了一個很重要的前提: 執行這段程式以前,畫面狀態是不是乾淨的? 這次的狀況就是典型的: 前一次操作留下來的狀態,被下一次操作拿去用了。 而且這種問題最麻煩的是,它表面上不像程式錯。 →畫面可以操作 →按鈕可以按 →資料也有送出去 控制端也有收到值。 整個流程看起來都正常。 只是送出去的目標,已經不是你以為的那一個。 這次如果沒有 LOG,其實很容易查到懷疑人生。 因為只看現場現象,會覺得: 「明明是設定到這個 Port,為什麼資料會跑到另一個 Port?」 但從 LOG 反推後才發現: 不是資料在中途被改掉。 而是畫面一開始拿到的狀態就已經錯了。 這也讓我再次覺得,設備軟體裡面有些初始化真的不能省。 尤其是這種跟物料、位置、Port、Slot 有關的功能。 只要下拉選單、暫存值、選擇狀態沒有清乾淨,就可能讓下一次操作吃到前一次的殘值。 這種問題不是邏輯完全寫錯。 而是程式假設: 「畫面現在的狀態一定是正確的。」 但現場最常出事的,往往就是這種假設。 做設備軟體久了會發現: 有些 Bug 不是因為程式不會動。 而是它真的會動。 只是它拿著上一次留下來的狀態,動到錯的地方。
愛心
3
留言
encourage first comment
有些話想說嗎 快分享出來彼此交流吧!