每天學點C++知識:用合適的工具來分析你的代碼
靜態代碼分析工具可簡化編碼過程,檢測出錯誤并幫助修復。有個國外團隊檢測了 200 多個 C/C++ 開源項目,包括了 Php、Qt 和 Linux 內核等知名項目。于是他們每天分享一個錯誤案例,并給出相應建議。伯樂在線翻譯組正在翻譯這個系列。今天的案例來自 LibreOffice 項目。
錯誤代碼
BOOL WINAPI DllMain( HINSTANCE hinstDLL,
DWORD fdwReason, LPVOID lpvReserved )
{
....
CreateThread( NULL, 0, ParentMonitorThreadProc,
(LPVOID)dwParentProcessId, 0, &dwThreadId );
....
} 解釋:
很久以前,我曾經在
業余時間接過一些項目。有一次我就接了一個項目,但是最后沒有搞定。這個項目本身就有問題,但是當時我并不知道。更麻煩的是,這個項目乍一看還蠻簡單的。
其實就是在 DllMain 方法中,當某些條件觸發時,用 Windows API 函數實現一些功能。我記不太清楚要實現哪些功能了,但是肯定不難。
我花了大量時間做這個項目,但是代碼就是不工作。更糟糕的是,如果我 創 建一個標準的新應用, 這段代碼 就沒問題,一旦我把 代碼 放到 DllMain 里去運行就不行。簡直是個謎,不是嗎?我最后還是 沒有找出問題的根源 。
多年以后的今天,我 使用 PVS-Studio 開發工具后,我突然意識到當年問題 的原因 。你 瞧 ,其實 DllMain 函數能正確執行的操作非常有限,因為(很多操作依賴的)DLL 庫并沒有被加載,所以你不能直接在 DllMain 里就直接執行任意的操作。
我們現在有了診斷工具,可以提醒程序員在 DllMain 里直接用哪些操作是危險的。現在我終于明白那時程序不能運行的原因了。
關于不能在 DllMain 里執行哪些操作的更多細節 ,可以查看(PVS-Studio)關于 V718 診斷信息的描述。
所以,上面那段 LibreOffice 的代碼片段很可能就無法工作。它能不能正常執行完全要靠運氣。
正確的代碼:
要修復這類錯誤其實很難。你需要重構整個代碼邏輯,讓 DllMain 函數里的操作越簡潔越好。
建議:
對于這類問題并沒有什么特別的建議。 你不可能什么都知道,每個人總有一天都會遇到類似的謎題 。我認為一個比較普遍的建議是這樣的:請仔細地閱讀和工作相關的各種文檔。但你還是要明白,人們無法預測每一個可能出現的問題。如果你把所有的時間都拿去閱讀文檔了,那又 怎么有時間 去編程呢?即使你已經讀了很多頁的文檔, 你也不確認有沒有漏看了某個文檔,而它是可以讓你免于犯錯的 。
我希望能給 出更加實用 的建議(來避免這些難以捕捉的錯誤),但是很遺憾我只能 想到 一條:使用靜態分析工具。 當然 這還是不能保證你就不會犯錯了。但是至少這么做會讓你犯錯的幾率降低。如果當年我有了這些工具,那我就絕對不會在 DllMain 里去調用我寫的那些代碼,那么我很可能就能節省大量時間,少死好多腦細胞。要知道,我對當時沒能搞定那個任務 一直 耿耿于懷!
這個錯誤由 PVS-Studio 靜態分析工具捕獲。錯誤文本:V718:“CreateThread”方法不應該在“DllMain”方法中調用。