剛剛 PicPick 又因 Memory Management 開始不正常運作,所以就索性來寫一下這篇文章 (BTW,筆者使用的是付費版的 PicPick,不是免費的家用個人版)。
Well, Memory Management 對軟體來說,是非常重要的一環,因為沒有處理好,100% 會出問題,什麼問題?最常見的就是當掉,在 Unix Platform 就是 Coredump 或 Segmentation Fault。
筆者在 2012 年的夏天開始學攝影,2013 年購買 CyberLink PhotoDirector,當時的意念是要支持國產軟體,所以特地購買 PhotoDirector 而不是 Lightroom;使用沒多久,就發現當掉情況還蠻常遇到的,但重新啟動再繼續,也勉強還能接受(坦白說,那當掉的頻率有點偏高,高到不應該做 release);繼續使用後發現有 bug,就跟 CyberLink 反應,當時 CyberLink 希望筆者將資料送給它們,讓它們可以在公司內部重現這個 bug 後再加以修復,筆者就同意將資料送過去 (若干張在野柳地質公園所拍攝的鳥類照片),只不過 CyberLink 在公司內部無法重現這個 bug,就問筆者是不是使用「特殊電腦」,筆者回道:「這電腦是在 PC Home 所購買的 Asus 桌上型電腦,不是特殊電腦。」並順道告知 Asus 桌上型電腦的型號。再經過一個多月,CyberLink 還是找不出原因,此時筆者也失去耐性,就上網購買 Lightroom,之後整個後製處理就全部移轉到 Adobe Lightroom。
當初在使用 PhotoDirector 的時候,就發現開一個 New Project,PhotoDirector 是把整個程式結束掉之後再重新啟動軟體,當時筆者就約略知道,這應該就是 Memory 的管理與回收有問題而所採取的暴力解決方案 ── 把整個 process 結束掉,再重新啟動一個新的 process。然而,轉到 Lightroom 之後才發現,原來 Lightroom 重新再開一個 Catalog,它也是將整個 process 結束掉,再重新啟動一個新的 process;Ah! 原來 Specifications 是這樣抄來抄去的啊!連暴力解決方式也照抄喔!實際上,應該是 CyberLink PhotoDirector 模仿 Adobe Lightroom 的規格,因為 Adobe Lightroom 1.0 是在 2007 年所推出,而 CyberLink PhotoDirecor 1.0 是在 2011 年所推出;只不過,Adobe 是全世界頂尖的軟體公司,怎麼會在 Lightroom 這個 Product Line 使用這麼低階的暴力解決方案,對此筆者是感到有些不解,Adobe InDesign 就沒有這樣搞呀,怎麼 Lightroom 會這樣搞?
大約五年前吧,筆者在台北市立聯合醫院的忠孝分院,當場目擊醫師所使用的醫療軟體當掉,由於檢測儀器是美國奇異公司的產品,筆者當下以為是奇異公司的醫療軟體,就順口說:Woh! 奇異的軟體也會當掉喔!醫師就笑笑回說:「不是奇異,是台灣做的,然後找了很久,一直找不到原因。」筆者當下就回說:Memory Problems!八九不離十是 Memory Problems!(筆者說的是程式邏輯在使用虛擬記憶體時出錯,所以造成當機;醫師有可能以為筆者講的是硬體的 DRAM)
像這種在醫療現場不定時出現的 bug ── 當掉,可行的除錯方案,就是設置一台備份電腦與一位 On-Site Software Engineer,然後透過 Debugger 在原本的電腦上跑 Debug Version,此時軟體的執行速度一定會變慢很多,這就要請醫師與病人忍耐一下,當 bug 出現時,醫師就改用備份電腦再重新啟動醫療軟體繼續看病,然後 On-Site Software Engineer 就可以透過 Debugger 找出當掉的原因。
軟體當掉,除了 Divide by Zero 之外,其它大部分的原因就是 Memory Problems,例如 Array/Stack Bound Read, Array/Stack Bound Write,Null Pointer Read, Null Pointer Write、Free Memory Read、Free Memory Write 等等;此外,如果不同軟體之間有相互溝通與協同合作,則 Race Condition Bug 也有可能會造成 Coredump 或 Segmentation Fault。以筆者的經驗而言,Memory Problems 比較好找也很容易解決,而 Race Condition Bug 則是比較棘手,因為得先查出「是什麼樣的互動順序」才會引發這個 bug,之後必須控制互動的順序去重現這個 bug!
在筆者的軟體研發生涯當中,沒有遇過找不出原因的 bug,全部都找得出來,即使少數的 bug 在公司內部無法複製重現,但到客戶端的現場做 On-Site Debugging,也全部都找得出原因;然而,即使全部都找得出原因,極少數的 bug 的確就是無解;例如,Sun Microsystem Network File System (NFS),即使透過 C System Call fsync(fd),要求它把 buffer data 寫到 disk file,呼叫完之後還是沒有作用,像這種 bug 是出在 Third Party 端,這就無解了 (Sun Microsystem 當然不會理你,只是沒想到這家令筆者倍感尊敬的公司,竟然也會不敵時勢潮流而煙飛灰滅!看來還是賣飲料的最好,基業長青到超過百年)!Wow! 這個無解的 bug 是距今至少 24 年前的事情,筆者怎麼還記得這麼清楚!哈哈哈!
根據上述所見到的當掉現象與常見原因,有些讀者可能想到了 C++ Smart Pointers,例如 std::unique_ptr 以及 std::shared_ptr 等等;其實這些語法與 Template Library 只是解決了 Memory Leak Problems,其它諸如 ABR、ABW、NPR、NPW 等 Memory Problems 還是沒有解決;此外,筆者是 LKK 工程師,所以會覺得這些由 Template 所寫成的 Library 是過於臃腫,會降低程式的執行效率與使用過多的記憶體,因此不會去使用這些東西;但如果你的應用程式主要目的是要靈活地處理瞬息多變的需求與規格、而不需要在意程式的執行效率以及使用過多的記憶體,那就可以使用!
好了,今天就寫到這裡,Have a nice day!