




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、編寫無錯的程序,作為一個程序員,你在寫每一行代碼時應該始終保持如履薄冰的危機感。,由來,編程精粹,Steve Maguire,電子工業(yè)出版社 作者是Microsoft公司資深項目主管 以下的內容是個人對此書的理解,與大家共同探討,概述,基本要求 總則 函數(shù)的設計 函數(shù)的實現(xiàn) 編譯、調試、修改、合版本 進一步的建議 設計 實現(xiàn) 超越編碼 攻擊錯誤,總則,確立并堅持編碼的優(yōu)先順序我們推薦的編碼優(yōu)先順序: 正確性 可維護性/可讀性 可測試性 全局效率 一致性 大小 局部效率 個人表達方式/個人方便性 建立程序的DEBUG版本,同時維護DEBUG版本和發(fā)行版本。在DEBUG版本中加入能暴露程序錯誤的代
2、碼。 堅持徹底測試代碼(單元測試),即使延誤進度。不要依靠測試組測試你的代碼。 不要責怪測試員發(fā)現(xiàn)你的錯誤(驚訝,怎么會有這樣的問題?然后感謝測試員在問題到用戶手中之前發(fā)現(xiàn)了它),函數(shù)的設計,函數(shù)不僅僅要正確,而且在使用時要安全 (糖果機的界面) 函數(shù)的返回值不要同時作為錯誤代碼和正常的返回結果,讓使用者不容易忽視錯誤情況 仔細考慮函數(shù)的界面,是否容易被誤用(函數(shù)名稱、參數(shù)、返回值) 不要定義多用途且面面俱到的函數(shù) 不要設計太靈活的(無確切含義、空空洞洞)函數(shù)參數(shù) 讓你的函數(shù)在調用點顯得易讀 不要使用布爾參數(shù)輸入 編寫函數(shù),使其在有效輸入情況下不會失敗,減少調用者的錯誤檢查 使用注釋突出使用時
3、可能的異常情況,返回值,函數(shù)的返回值不要同時作為錯誤代碼和正常的返回結果,讓使用者不容易忽視錯誤情況 風險的代碼 char c ; c = getchar() ; if (c = EOF) ? 問題 getch()返回int型 在stdio.h種,#define EOF (-1) 如果變量 c 是無符號字符,if語句永遠不會成立 換一種做法 flag fGetChar(char * pch) ; char ch ; if (fGetCh( if (pbBuf != NULL) 問題 如果僅有pbBuf引用其指向的內存,在分配失敗時出現(xiàn)內存泄露 換一種做法 flag fResizeMemory(
4、void *ppv, size_t sizeNew) byte * ppb = (byte *)ppv ; byte * pbResize ; pbResize = (byte *)realloc(*ppb, sizeNew) ; if (pbResize != NULL) * ppb = pbResize ; return (pbResize != NULL) ; ,不要定義面面俱到的函數(shù),風險的代碼 void * realloc(void *pv, sizet size) ; 如果內存塊的新長度小于老長度 如果內存塊的新長度大于老長度 如果內存不夠 如果pv是NULL = malloc 如
5、果pv不是NULL,但新長度為0 = free 如果pv是NULL,新長度為0 = ? 問題 對不同pv的操作是否有用? 如何處理這些情況? 換一種做法 ASSERT的使用,pv = NULL | size = 0 fGrowMemory(void *ppv, size_t sizeLarger) ; fShrinkMemory(void *pv, size_t sizeSmaller) ;,明確定義函數(shù)參數(shù),避免摸棱兩可,風險 char *CopySubStr(char * strTo, char *strFrom, size_t size) ; char * strStart = strT
6、o ; while (size - 0) * strTo + = * strFrom + ; *strTo = 0 ; return strStart) ; 問題 如果size大于strFrom的長度,? 換一種做法 明確規(guī)定,strFrom必須包含size個字符 ASSERT(strTo!=NULL void UnsignedToHexStr(unsigned u, char * str) ;,返回失敗的函數(shù),編寫函數(shù),使其在有效輸入情況下不會失敗 減少調用者的錯誤檢查 風險的代碼 char tolower(char ch) if (ch =A 換一種做法 如果輸入不是字母,則返回輸入的字符
7、 不接收非字母的輸入(ASSERT),函數(shù)的注釋,使用注釋突出使用時可能的異常情況 風險的代碼 pv = realloc( pv, sizeNew) ; 問題 內存泄露 替你的客戶著想 /* realloc(pv, size) 典型用法: void * pvNew ; pvNew = realloc(pv, sizeNew) ; if ( NULL != pvNew ) pv = pvNew ; / success else / failue / pvNew為NULL,不要丟掉pv的內存 */,實現(xiàn),保證程序良好的可讀性,保證代碼的中注釋行與空行所占比例大于30% 使用斷言。在以下情況下應該使
8、用斷言: 利用斷言確認函數(shù)的參數(shù) 用斷言保證沒有定義的特性不被使用(或者去除無定義的特性). 將你對程序開發(fā)運行環(huán)境(OS, Compiler, Hardware)的假設用斷言給出 用斷言檢查不可能發(fā)生的情況 編寫防錯性處理程序,但防止錯誤之后用斷言宣布發(fā)生錯誤 對復雜的斷言加上注釋 盡量編寫和測試小塊代碼,即使測試影響進度,函數(shù)規(guī)模限制在200行以內 使用嚴格定義的、可移植的數(shù)據類型 避免使用嵌套的?:運算符 一個任務應該一次完成(如果多段代碼重復做同一件事,意味者存在問題) 避免無關緊要的if語句(草率設計、粗心實現(xiàn)的結果) 對特殊情況,只在程序的一個地方處理 不同類型的操作符混合使用時,
9、使用括號隔離之 盡量避免使用返回錯誤的函數(shù),斷言,斷言的實現(xiàn) #ifdef NDEBUG #define assert(p) (void)0) #else # define assert(p) (p) ? (void)0 : (void) _assertfail( Assertion failed: %s, file %s, line %d _ENDL, #p, _FILE_, _LINE_ ) ) #endif 斷言與錯誤處理 斷言不等于錯誤處理 char *pcM = (char *) malloc(sizeWant) ; ASSERT(NULL != pcM) ; 。 。 斷言不等同與狀
10、態(tài)提示 VC+中的TRACE,斷言的使用(一),利用斷言確認函數(shù)的參數(shù) void memcpy(void *pvTo, void *pvFrom, size_t size) assert( NULL != pvTo 。 。,斷言的使用(二),用斷言檢查不可能發(fā)生的情況 switch state) 。 default: ASSERT(FALSE) ; 編寫防錯性處理程序,但防止錯誤之后用斷言宣布發(fā)生錯誤 / get Name from self-gen temp. file. Extern file * pfSaveBuffFile ; BOOL getName(char * pcName) i
11、f (8 != fread(pcName, 1, 7, fpSaveBuffFile) / this must not occur ASSERT(FALSE) ; / do some thing 。 。 對復雜的斷言加上注釋,實現(xiàn)(陷阱的回避),盡量編寫和測試小塊代碼,即使測試影響進度,函數(shù)規(guī)模限制在200行以內 使用嚴格定義的、可移植的數(shù)據類型 High C環(huán)境下B型機的數(shù)據類型 typedef unsigned short _UI; typedef unsigned char _UC; typedef unsigned short _US; typedef unsigned int _UL
12、; 不同類型的操作符混合使用時,使用括號隔離之 混合操作類型 word = high 8 + low ; / 運算符優(yōu)先級錯誤 while (ch = getchar() != EOF) . 換一種做法 word = high 8 | low ; word = high * 256 + low ; while (ch = getchar() != EOF) . 盡量避免使用返回錯誤的函數(shù) 讓函數(shù)始終正確工作 將同樣的錯誤處理部分獨立開來,實現(xiàn)(消除冗余,改進算法),提示 一個任務應該一次完成(如果多段代碼重復做同一件事,意味者存在問題) 避免無關緊要的if語句(草率設計、粗心實現(xiàn)的結果) 避免
13、使用嵌套的?:運算符 對特殊情況,只在程序的一個地方處理 理由 避免維護中無意識地遺漏而導致錯誤。 簡單地解決讓程序員不再話時間尋找更號的解決方法。,實現(xiàn)(消除冗余,改進算法),代碼(一) void * memchr(void *pv, unsigned char ch, size_t, size) unsigned char * pch = (unsignecd char *) pv ; unsigned char * pchEnd = pch + size ; while (pch pchEnd ,實現(xiàn)(消除冗余,改進算法),代碼(二) if (NULL = pHead-next) pHe
14、ad-next = pNew ; else TNode * pGo = pHead-next ; while (pGo-next != NULL) pGo = pGo-next ; pGo-next = pNew ; 換一種做法 pGo-next = pHead ; while (pGo-next != NULL) pGo = pGo-next ; pGo-next = pNew ;,進一步考慮(設計),設計一個特征前,先仔細考慮是否是用戶需要 不設自由特征 不允許沒有必要的靈活性 對關鍵的算法使用二個算法來確認前者 不要等待錯誤發(fā)生,在代碼啟動前使用初始檢查程序以保證程序運行環(huán)境的一致性,進
15、一步考慮(實現(xiàn)),時刻注意表達式是否會上溢、下溢 明確設計,并精確(不是近似)實現(xiàn)設計 避免使用有風險的語言慣用語 只引用屬于自己的存貯空間 注意是否引用已經釋放的空間 指向輸出的指針不是指向工作緩沖區(qū)的指針 避免向靜態(tài)(全局)變量存貯區(qū)傳遞數(shù)據 不要編寫依賴于其他函數(shù)內部實現(xiàn)的函數(shù) 不要使用希奇古怪的C慣用語 不要追求緊湊的代碼(不代表高效的機器碼) 考慮你的代碼將給新手讀,超越編碼,消除代碼運行的隨機性,使錯誤可再現(xiàn)。去除未定義的(隨機的)特性、無用的數(shù)據內容等。 在DEBUG版中將無用的信息抹掉(換以固定的數(shù)字),以免被錯誤使用 如果某件事很少發(fā)生,設法使其經常發(fā)生。確定子系統(tǒng)會發(fā)生哪些
16、事情,并使它們經常發(fā)生;如果發(fā)現(xiàn)子系統(tǒng)中有很少發(fā)生的行為,千方百計使其重現(xiàn)。 保存內部調試信息,進行更強的錯誤檢查 主動出擊,建立子系統(tǒng)檢查,在適當時候確認子系統(tǒng)的狀態(tài) 仔細設計程序的測試代碼,任何選擇都應該經過考慮 設計透明的一致性檢查,在正常的程序運行過程中自動檢查一致性 保證DEBUG版本的運行,即使其大小和速度不盡人意,超越編碼(讓錯誤固定出現(xiàn)),消除代碼運行的隨機性,使錯誤可再現(xiàn)。去除未定義的(隨機的)特性、無用的數(shù)據內容等。 在DEBUG版中將無用的信息抹掉(換以固定的數(shù)字),以免被錯誤使用 如果某件事很少發(fā)生,設法使其經常發(fā)生。確定子系統(tǒng)會發(fā)生哪些事情,并使它們經常發(fā)生;如果發(fā)現(xiàn)
17、子系統(tǒng)中有很少發(fā)生的行為,千方百計使其重現(xiàn)。 代碼 void FreeMemory(void *pv) ASSERT(pv != NULL) ; #ifdef DEBUG memset(pv, bGarbage, sizeofBlock(pv) ; #endif free(pv) ; ,超越編碼(主動出擊),保存內部調試信息,進行更強的錯誤檢查 主動出擊,建立子系統(tǒng)檢查,在適當時候確認子系統(tǒng)的狀態(tài) 仔細設計程序的測試代碼,任何選擇都應該經過考慮 設計透明的一致性檢查,在正常的程序運行過程中自動檢查一致性 代碼 flag fCreatBlockinfo(byte * pbNew, size_t sizeNew) ;
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 拱墅區(qū)小學數(shù)學試卷
- 高一期末深圳數(shù)學試卷
- 房山區(qū)高三數(shù)學試卷
- 高一金太陽數(shù)學試卷
- 福建英語數(shù)學試卷
- 2025年03月山東威海市中心醫(yī)院山東省博士后創(chuàng)新實踐基地招聘20人筆試歷年專業(yè)考點(難、易錯點)附帶答案詳解
- 財務評價培訓課件模板
- 2025至2030達瓦納油行業(yè)市場深度研究與戰(zhàn)略咨詢分析報告
- 阜新實驗月考數(shù)學試卷
- 東莞市初三題目數(shù)學試卷
- 2023-2024學年滬科版(2019)高中信息技術必修二第三單元項目五《規(guī)劃并連接數(shù)字家庭系統(tǒng)的網絡-組建小型信息系統(tǒng)網絡(一)》說課稿
- 石油行業(yè)設備管理規(guī)范
- 汕頭市防汛防旱防風防凍應急預案
- 2023年高考遼寧卷化學真題(解析版)
- 2023-2024學年廣東省深圳市福田區(qū)七年級(下)期末數(shù)學答案
- 2024版商戶入駐合同
- 和公司直播合作協(xié)議書范本
- 兒科護理學高職全套教學課件
- 光伏發(fā)電工程建設標準工藝手冊(2023版)
- 北師大版八年級數(shù)學下冊??碱}專練專題18平行四邊形中的周長和面積問題(原卷版+解析)
- 山東省濟寧市曲阜市2023-2024學年七年級下學期期末數(shù)學試題
評論
0/150
提交評論