靜態(tài)代碼分析工具可簡(jiǎn)化編碼過(guò)程,檢測(cè)出錯(cuò)誤并幫助修復(fù)。有個(gè)國(guó)外團(tuán)隊(duì)檢測(cè)了 200 多個(gè) C/C++ 開(kāi)源項(xiàng)目,包括了 Php、Qt 和 Linux 內(nèi)核等知名項(xiàng)目。于是他們每天分享一個(gè)錯(cuò)誤案例,并給出相應(yīng)建議。今天的案例來(lái)自 LibreOffice 項(xiàng)目。
錯(cuò)誤代碼
BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ){ .... CreateThread( NULL, 0, ParentMonitorThreadProc, (LPVOID)dwParentProcessId, 0, &dwThreadId ); ....}解釋?zhuān)?/strong>
很久以前,我曾經(jīng)在業(yè)余時(shí)間接過(guò)一些項(xiàng)目。有一次我就接了一個(gè)項(xiàng)目,但是最后沒(méi)有搞定。這個(gè)項(xiàng)目本身就有問(wèn)題,但是當(dāng)時(shí)我并不知道。更麻煩的是,這個(gè)項(xiàng)目乍一看還蠻簡(jiǎn)單的。
其實(shí)就是在 DllMain 方法中,當(dāng)某些條件觸發(fā)時(shí),用 Windows API 函數(shù)實(shí)現(xiàn)一些功能。我記不太清楚要實(shí)現(xiàn)哪些功能了,但是肯定不難。
我花了大量時(shí)間做這個(gè)項(xiàng)目,但是代碼就是不工作。更糟糕的是,如果我創(chuàng)建一個(gè)標(biāo)準(zhǔn)的新應(yīng)用,這段代碼就沒(méi)問(wèn)題,一旦我把代碼放到 DllMain 里去運(yùn)行就不行。簡(jiǎn)直是個(gè)謎,不是嗎?我最后還是沒(méi)有找出問(wèn)題的根源。
多年以后的今天,我使用?PVS-Studio 開(kāi)發(fā)工具后,我突然意識(shí)到當(dāng)年問(wèn)題的原因。你瞧,其實(shí) DllMain 函數(shù)能正確執(zhí)行的操作非常有限,因?yàn)椋ê芏嗖僮饕蕾?lài)的)DLL 庫(kù)并沒(méi)有被加載,所以你不能直接在 DllMain 里就直接執(zhí)行任意的操作。
我們現(xiàn)在有了診斷工具,可以提醒程序員在 DllMain 里直接用哪些操作是危險(xiǎn)的。現(xiàn)在我終于明白那時(shí)程序不能運(yùn)行的原因了。
關(guān)于不能在 DllMain 里執(zhí)行哪些操作的更多細(xì)節(jié),可以查看(PVS-Studio)關(guān)于 V718 診斷信息的描述。
所以,上面那段 LibreOffice 的代碼片段很可能就無(wú)法工作。它能不能正常執(zhí)行完全要靠運(yùn)氣。
正確的代碼:
要修復(fù)這類(lèi)錯(cuò)誤其實(shí)很難。你需要重構(gòu)整個(gè)代碼邏輯,讓 DllMain 函數(shù)里的操作越簡(jiǎn)潔越好。
建議:
對(duì)于這類(lèi)問(wèn)題并沒(méi)有什么特別的建議。你不可能什么都知道,每個(gè)人總有一天都會(huì)遇到類(lèi)似的謎題。我認(rèn)為一個(gè)比較普遍的建議是這樣的:請(qǐng)仔細(xì)地閱讀和工作相關(guān)的各種文檔。但你還是要明白,人們無(wú)法預(yù)測(cè)每一個(gè)可能出現(xiàn)的問(wèn)題。如果你把所有的時(shí)間都拿去閱讀文檔了,那又怎么有時(shí)間去編程呢?即使你已經(jīng)讀了很多頁(yè)的文檔,你也不確認(rèn)有沒(méi)有漏看了某個(gè)文檔,而它是可以讓你免于犯錯(cuò)的。
我希望能給出更加實(shí)用的建議(來(lái)避免這些難以捕捉的錯(cuò)誤),但是很遺憾我只能想到一條:使用靜態(tài)分析工具。當(dāng)然這還是不能保證你就不會(huì)犯錯(cuò)了。但是至少這么做會(huì)讓你犯錯(cuò)的幾率降低。如果當(dāng)年我有了這些工具,那我就絕對(duì)不會(huì)在 DllMain 里去調(diào)用我寫(xiě)的那些代碼,那么我很可能就能節(jié)省大量時(shí)間,少死好多腦細(xì)胞。要知道,我對(duì)當(dāng)時(shí)沒(méi)能搞定那個(gè)任務(wù)一直耿耿于懷!
這個(gè)錯(cuò)誤由 PVS-Studio 靜態(tài)分析工具捕獲。錯(cuò)誤文本:V718:“CreateThread”方法不應(yīng)該在“DllMain”方法中調(diào)用。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)武林網(wǎng)的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接
新聞熱點(diǎn)
疑難解答