作者:陳甫鸼
來源:知乎,可點(diǎn)擊閱讀原文
你們公司允許使用C++STL嗎?各位老鐵可以在我價(jià)值¥2700的評論區(qū)留言。

最初開始禁用 C++ STL,是因?yàn)樵缙陧?xiàng)目編碼實(shí)踐中留下的慣例,被后來的程序員繼承下來。老項(xiàng)目中這種選擇尤其地多。不過如果有人將其上升到公司行為在不同項(xiàng)目中全面禁用 STL,則沒有必要,而且我傾向于做這種決定的人并不理解 C++ 編譯系統(tǒng)。
一般來說,項(xiàng)目中禁用 C++ 多見于兩種具體場景:項(xiàng)目的產(chǎn)出產(chǎn)品為函數(shù)庫 OR 需要引用第三方函數(shù)庫。
具體地來說,有三個主要原因:
第一個原因是二進(jìn)制邊界混亂。對需要在項(xiàng)目中使用第三方函數(shù)庫的程序員來說,二進(jìn)制邊界是個頭痛的問題。C++ 在這一方面本身就處理得不算好,加上模板后起到的是雪上加霜的后果。沒有經(jīng)驗(yàn)的程序員會貪圖方便而在公開頭文件中使用 C++ 模板,如果這時調(diào)用方的編譯器選項(xiàng)設(shè)置或 STL 版本和編譯方不同,那么就可能出現(xiàn)同樣的頭文件在不同的環(huán)境下二進(jìn)制布局不符的情況。
順便說一句,在過去十年里,各個主流編譯器附帶的 STL 版本變化節(jié)奏不慢,所以這種由于編譯環(huán)境不同而導(dǎo)致的 bug 并不算罕見,但缺乏匯編知識的用戶難以排查。
第二個原因是不愿使用異常。如今除了 Android 上的 STLPort 關(guān)閉異常,大部分主流 C++ STL 實(shí)現(xiàn)里都無法脫離異常使用 STL。異常帶來的問題主要是兩個:性能下降,代碼膨脹。這幾年 C++ 編譯器在性能方面的改進(jìn)很多,good path 的性能問題已經(jīng)基本沒有,但代碼膨脹問題卻沒有太多改善,甚至這個性能問題的一部分解決方案就是以代碼膨脹為代價(jià)。我寫過一篇短文比對過 Android 上 gcc 4.6 在有無異常的情況下的匯編代碼邏輯,可以看到,啟動異常時生成的匯編代碼量多出了相當(dāng)一部分(我的例子中是 50%),用于處理各種隱含代碼中的異常問題。這一條在手機(jī)系統(tǒng)中有時候會引起意想不到的麻煩,比如軟件升級后導(dǎo)致 app 在低存儲容量的手機(jī)中安裝失敗。順便說一句,這個問題并不是 gcc 獨(dú)有,clang 上生成的代碼是一樣的。參考:http://dummydigit.net/posts/2014-01-01-23-30-1.html
最后一個原因是 C 兼容。嚴(yán)格地說,STL 在這個問題上算是躺槍,這個坑在很多具體的場景中也是因?yàn)楫惓6耄@個問題的麻煩程度比前兩個問題更高。比如 gcc 在編譯純 C 代碼時默認(rèn)關(guān)閉 -fexceptions 選項(xiàng),因此這樣編譯出來的代碼中沒有異常處理相關(guān)的棧展開。如果某個 C++ 項(xiàng)目引用了一個第三方 C 項(xiàng)目,它很難確保那個 C 項(xiàng)目給出的二進(jìn)制代碼中正確進(jìn)行了異常處理并保證代碼服從異常安全操作。這種場景下混用 C/C++ ,就可能在拋出異常時莫名其妙地崩潰或者出現(xiàn) C 代碼區(qū)段中的資源泄漏,特別是 expat 那種大量利用回調(diào)的代碼結(jié)構(gòu)。要規(guī)避這種風(fēng)險(xiǎn)并非不可能,但需要 C 的架構(gòu)部分做修改,比如使用 DOM 那種樹形結(jié)構(gòu),這種做法對歷史項(xiàng)目而言又很難辦到。換言之,如果一個項(xiàng)目出于種種原因需要保持 C 兼容,而 STL 就屬于其中一個不可控的變數(shù),與其相信程序員不犯錯,不如直接禁用更可控一些。參考:Code Gen Options
要解決二進(jìn)制相關(guān)的問題很簡單:整個項(xiàng)目的所有相關(guān)代碼在同一個代碼基上編譯,強(qiáng)制打開編譯選項(xiàng)添加異常代碼,并去除一切二進(jìn)制依賴。但對很多小公司來說,引入這樣的系統(tǒng)對配置管理的要求較高。如果一部分依賴關(guān)系來自自己并不了解的第三方代碼,輕易修改編譯選項(xiàng)可能帶來的風(fēng)險(xiǎn)與第三方代碼庫的規(guī)模成正比。退一步說,即便團(tuán)隊(duì)里真的有強(qiáng)大的配置管理工程師能夠搞定一切,他們也不會有能力解決代碼膨脹問題,除非他們有權(quán)決定換一個編譯器。相比之下,前面朋友所說的所謂性能或者編譯出錯時糟糕的可讀性,在我看來反倒是次要因素,而且這些缺陷都正在新的編譯器中逐步得到解決或改善,比如 clang。
往期推薦