揭秘C語言寶刀未老的秘密!80%的程序員都懵了

C語言瓜贾,在今天來說是一種特殊的編程語言诺祸。只有極少數(shù)人真的可以用C進(jìn)行編程,而且我們中很大一部分人都對(duì)C有自己的看法祭芦。緩沖區(qū)溢出筷笨,棧溢出,整型數(shù)據(jù)溢出龟劲,C有很多廣為人知缺陷胃夏,而這些缺陷被人們隨意傳播,甚至那些不熟悉C的人們昌跌。我自己已經(jīng)有10念沒有接觸C了仰禀,由于這樣或那樣的原因。開始的額時(shí)候蚕愤,編譯器是很昂貴的(在免費(fèi)的UNIX被發(fā)布之前)而且很慢答恶,那時(shí)的環(huán)境是很糟的囊榜。而且,所有關(guān)于C的恐怖故事讓我覺得我這么一個(gè)小小的普通程序員怎么可以寫出可靠的C程序亥宿。

撇過一些我直接從別的地方復(fù)制粘貼過來的很多小的C模塊不說卸勺,我自己寫的第一個(gè)C程序是Converge?VM。其中有兩件事情讓我驚呆了:-o 烫扼。第一曙求,寫C程序原來不是那么難。事后我才知道我年輕的時(shí)候浪費(fèi)時(shí)間寫匯編代碼這件事在心理上給我了很大的支持映企,畢竟C是高級(jí)一點(diǎn)的匯編語言悟狱。一旦一個(gè)人理解了像指針(可以說是低級(jí)語言中最微妙的概念,因?yàn)檎鎸?shí)世界中沒有相對(duì)應(yīng)的比喻)這樣的概念堰氓。第二件事情是挤渐,Converge VM沒有像我期待那樣滿是bug。

實(shí)際上双絮,忽略可能在任何編程語言上都存在的邏輯錯(cuò)誤浴麻,到目前為止在Converge VM中引發(fā)實(shí)際問

題的只有兩個(gè)只針對(duì)C才會(huì)有的錯(cuò)誤(主意,我肯定還有很多潛伏的bug囤攀,但是我情形還沒有碰上太多)软免。第一個(gè)錯(cuò)誤是,一個(gè)list沒有以\0(C中經(jīng)典的錯(cuò)誤)焚挠,這個(gè)問題花了很長(zhǎng)時(shí)間去調(diào)試膏萧。另一個(gè)錯(cuò)誤則神奇的多了,花了我好幾個(gè)月時(shí)間蝌衔。Converge 垃圾回收器可以謹(jǐn)慎地根據(jù)指針回收隨意分配的內(nèi)存空間榛泛。在所有的現(xiàn)在結(jié)構(gòu)中,指針都指的是字和字對(duì)齊的邊界噩斟。然而曹锨,已經(jīng)分配的內(nèi)存塊在長(zhǎng)度上常常不是字和字對(duì)齊的。 (In all modern architectures, pointers have to live on word-aligned boundaries.However, malloc'd chunks of memory are often not word-aligned in length.) 所以有時(shí)候垃圾回收器會(huì)在一個(gè)內(nèi)存塊位置為4的地方嘗試讀取4bytes亩冬,即使那個(gè)內(nèi)存塊是5bytes長(zhǎng)艘希。換句話來說硼身,垃圾回收器嘗試讀入一塊數(shù)據(jù)的1bytes和內(nèi)存中理論上沒有權(quán)限的3bytes隨機(jī)數(shù)據(jù)硅急。罕見和神奇的是,這導(dǎo)致的錯(cuò)誤幾乎沒法解釋佳遂。但是不夸張的說营袜,在多少編程語言中一個(gè)人可以遞歸地加上垃圾回收器?

我和Converge VM的經(jīng)歷不怎么不符合我之前的偏見丑罪。我已經(jīng)

慢慢承認(rèn)C程序會(huì)隨機(jī)出現(xiàn)segfault荚板,丟數(shù)據(jù)凤壁,而且常常會(huì)像Vikings(維京海盜)去Lindisfarne一樣。對(duì)比來看跪另,用高級(jí)語言編寫的程序會(huì)按照正常邏輯和可以預(yù)料的模式報(bào)錯(cuò)拧抖。漸漸地,這些問題在我日常使用的我可以信任的這些用C寫的程序中免绿,我都碰到了唧席。我不記得上次這些程序發(fā)生大問題的時(shí)候了。這些不會(huì)崩潰嘲驾,也會(huì)優(yōu)雅的處理次要的錯(cuò)誤淌哟。就算,我對(duì)這些軟件(我使用OpenBSD9年了辽故,所以沒有比這些質(zhì)量更好的軟件了)極度挑剔徒仓,還有一些明顯的原因以至于為什么它為什么如此可靠:它被很多人使用,而這些人幫助我們找出bug誊垢。軟件已經(jīng)被開發(fā)出來很長(zhǎng)時(shí)間了掉弛,所以之前的版本都存在bug。并且喂走,坦誠(chéng)一點(diǎn)狰晚,只有相當(dāng)能干的程序員首選會(huì)傾向于C。但是缴啡,仍然存在一個(gè)根本的問題:為什么用C寫的程序堅(jiān)如磐石壁晒?

過了寫論文這段黑暗的時(shí)期之后,我最近做了一點(diǎn)C編程业栅。對(duì)于長(zhǎng)時(shí)間沒有著手寫C程序的人秒咐,想妥妥地發(fā)封郵件都沒譜了。這些年碘裕,我都是通過ssh在遠(yuǎn)程機(jī)器用sendmail發(fā)送郵件的携取。這解決了很多問題(比如黑名單),在很多網(wǎng)絡(luò)中它也有問題(尤其是無線網(wǎng)絡(luò))帮孔,一個(gè)過多的網(wǎng)絡(luò)連接會(huì)被拋掉雷滋。檢查郵件是否發(fā)送是很煩人的過程。所以仔細(xì)檢查它的設(shè)計(jì)后文兢,我打算寫一個(gè)簡(jiǎn)單的工具集來穩(wěn)妥地通過ssh發(fā)送郵件晤斩。最終的程序 -?extsmail?- 比我之前所期待的有更多的功能,但是最基礎(chǔ)的思想就是通過外部的命令比如ssh簡(jiǎn)單的重試發(fā)送郵件姆坚,直到成功發(fā)送澳泵。我還想讓這個(gè)工具集盡可能占用資源少還實(shí)用,還可移植兼呵。這必然決定應(yīng)該用C寫extsmail兔辅。然后我決定嘗試盡可能地寫這個(gè)程序腊敲,就當(dāng)是實(shí)驗(yàn)吧。用傳統(tǒng)的UNIX方式维苔,只依賴可靠的UNIX分發(fā)版所提供的功能碰辅,而且容錯(cuò)能力強(qiáng)。在做的過程中介时,做了兩份關(guān)于用C寫程序的新手觀察資料乎赴。

第一個(gè)觀察不是太明顯。因?yàn)橛肅寫的程序有無數(shù)多種錯(cuò)誤方式潮尝,我比平時(shí)更加細(xì)心榕吼。特別的,任何內(nèi)存塊的的操作都會(huì)引發(fā)非常危險(xiǎn)的緩沖溢出類型錯(cuò)誤勉失。然而羹蚣,在一個(gè)高級(jí)語言中,我可能會(huì)比較懶乱凿,心想“嗯顽素,我索引數(shù)組的時(shí)候是不是應(yīng)該給這個(gè)值減一?先跑一遍看看”徒蟆。在C中胁出,我會(huì)想“OK,坐下來想想原因”段审。諷刺的是全蝶,跑程序和發(fā)現(xiàn)問題所花的時(shí)間和坐下來思考的時(shí)間是不一樣的,除了坐下來思考更加耗費(fèi)腦力。

第二個(gè)觀察,是我之前從沒有碰到過的会前,在C中沒有異常處理。如果始苇,比如說extsmail,要提高容錯(cuò)能力筐喳,就得自己不得不處理所有可能的錯(cuò)誤催式。從一方面來說,這是非常痛苦的避归,extsmail有很大一部分比例(大概40%)都在檢查和去除錯(cuò)誤荣月,雖然UNIX系統(tǒng)方法已經(jīng)很仔細(xì)的處理出錯(cuò)的情況了。換句話說槐脏,當(dāng)在C中調(diào)用一個(gè)方法喉童,比如stat的時(shí)候,文檔會(huì)列出所有失敗的情況顿天。用戶可以很容易的選擇應(yīng)該在程序中修復(fù)哪個(gè)情況堂氯,哪些致命錯(cuò)誤應(yīng)該進(jìn)一步處理(在extsmail中,內(nèi)存不足就是致命錯(cuò)誤)牌废。這就是在思維模式上基于語言的異常處理方式巨大的不同點(diǎn)咽白,經(jīng)典的哲學(xué)是正常地寫代碼,僅在少數(shù)情況下寫try ... catch語句塊來處理特定錯(cuò)誤(很少碰到的錯(cuò)誤)鸟缕。Java晶框,用受控制的異常,以不同的方式告訴用戶“當(dāng)調(diào)用這個(gè)方法的時(shí)候懂从,你需要try catch特定的異呈诙危”。

我明白了一件事情番甩,當(dāng)希望軟件足夠的強(qiáng)壯(魯棒性)的時(shí)候侵贵,基于異常的軟件設(shè)計(jì)是不合適的。而需要明確的是知道一個(gè)方法返回的或者拋出的錯(cuò)誤或者異常缘薛,然后根據(jù)情況去處理窍育。在現(xiàn)在的IDE中,可以根據(jù)寫的方法自動(dòng)顯示會(huì)拋出哪些異常宴胧,最多也就只能做到這一點(diǎn)了漱抓。理論上,面向?qū)ο笾械淖宇惡投鄳B(tài)意味著預(yù)編譯的庫(kù)不能根據(jù)寫的代碼確定會(huì)不會(huì)拋異常(因?yàn)樽宇悤?huì)重寫方法恕齐,會(huì)拋出不同的錯(cuò)誤)乞娄。從實(shí)用方面來說,我懷疑這么多方法都會(huì)拋出很多不同的異常显歧,這會(huì)讓用戶懵了补胚。對(duì)比UNIX中的方法,就非常注意追迟,它們會(huì)盡量減少返回給用戶的錯(cuò)誤的數(shù)量溶其,和一些內(nèi)部錯(cuò)誤,或者收集歸類錯(cuò)誤敦间。進(jìn)一步瓶逃,我也懷疑那些依賴異常處理的很多庫(kù)需要大幅度的進(jìn)行重寫來減少拋出的異常數(shù)量直到一個(gè)合理的數(shù)值。再進(jìn)一步廓块,方法的調(diào)用者應(yīng)該決定什么錯(cuò)誤應(yīng)該次要的厢绝,可以恢復(fù)的,哪些會(huì)導(dǎo)致重要的問題带猴,甚至導(dǎo)致程序結(jié)束;受控制的異常,被調(diào)用者強(qiáng)制處理的異常昔汉,就忘了這一點(diǎn)。

如果有喜歡C/C++的小伙伴加一下裙:775356268一起學(xué)習(xí)交流拴清。

Henry Spencer 說靶病,“那些不懂UNIX的人注定要可憐地重新發(fā)明輪子”会通。這就是為什么這么多用C寫的程序比我們所提出的偏見更加堅(jiān)固,UNIX文化娄周,在計(jì)算機(jī)主流里涕侈,最古老和最明智的文化,已經(jīng)發(fā)現(xiàn)很多把C的局限和缺陷變成優(yōu)勢(shì)的方法煤辨。就像我經(jīng)歷的裳涛,慢慢地我才明白了這點(diǎn)。綜上众辨,如果沒有經(jīng)過大量的思考端三,我不建議使用C。如果使用C鹃彻,那最終的軟件堅(jiān)如磐石郊闯,但開發(fā)會(huì)花費(fèi)大量人力。

本文章由網(wǎng)絡(luò)摘抄分享浮声,如侵刪虚婿。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市泳挥,隨后出現(xiàn)的幾起案子然痊,更是在濱河造成了極大的恐慌,老刑警劉巖屉符,帶你破解...
    沈念sama閱讀 211,639評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件剧浸,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡矗钟,警方通過查閱死者的電腦和手機(jī)唆香,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吨艇,“玉大人躬它,你說我怎么就攤上這事《校” “怎么了冯吓?”我有些...
    開封第一講書人閱讀 157,221評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)疮跑。 經(jīng)常有香客問我组贺,道長(zhǎng),這世上最難降的妖魔是什么祖娘? 我笑而不...
    開封第一講書人閱讀 56,474評(píng)論 1 283
  • 正文 為了忘掉前任失尖,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘掀潮。我一直安慰自己菇夸,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評(píng)論 6 386
  • 文/花漫 我一把揭開白布胧辽。 她就那樣靜靜地躺著峻仇,像睡著了一般公黑。 火紅的嫁衣襯著肌膚如雪邑商。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,816評(píng)論 1 290
  • 那天凡蚜,我揣著相機(jī)與錄音人断,去河邊找鬼。 笑死朝蜘,一個(gè)胖子當(dāng)著我的面吹牛恶迈,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播谱醇,決...
    沈念sama閱讀 38,957評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼暇仲,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了副渴?” 一聲冷哼從身側(cè)響起奈附,我...
    開封第一講書人閱讀 37,718評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎煮剧,沒想到半個(gè)月后斥滤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,176評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡勉盅,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評(píng)論 2 327
  • 正文 我和宋清朗相戀三年佑颇,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片草娜。...
    茶點(diǎn)故事閱讀 38,646評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡挑胸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出宰闰,到底是詐尸還是另有隱情茬贵,我是刑警寧澤,帶...
    沈念sama閱讀 34,322評(píng)論 4 330
  • 正文 年R本政府宣布议蟆,位于F島的核電站闷沥,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏咐容。R本人自食惡果不足惜舆逃,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧路狮,春花似錦虫啥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至砸抛,卻和暖如春评雌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背直焙。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工景东, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人奔誓。 一個(gè)月前我還...
    沈念sama閱讀 46,358評(píng)論 2 360
  • 正文 我出身青樓斤吐,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親厨喂。 傳聞我的和親對(duì)象是個(gè)殘疾皇子和措,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容