編寫優(yōu)質(zhì)無錯代碼_第1頁
編寫優(yōu)質(zhì)無錯代碼_第2頁
編寫優(yōu)質(zhì)無錯代碼_第3頁
編寫優(yōu)質(zhì)無錯代碼_第4頁
編寫優(yōu)質(zhì)無錯代碼_第5頁
已閱讀5頁,還剩9頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

1、編寫優(yōu)質(zhì)無錯代碼http:/LinuxA 01-08-19 21:59 500p ariesram-      一. 引言          八月上旬,深圳舉辦了一個討論會,主題是"編寫優(yōu)質(zhì)無錯代碼"。這個討論會吸引了深圳各大軟件公司,通信公司的程序員,系統(tǒng)分析員參加,并在討論會后紛紛表示,這種討論會很有實際價值,希望將這種形式的討論會繼續(xù)下去,形成一個論壇,以提高大家的編程水平和交換有價值的信息資料。   

2、;       這個活動的發(fā)起是從網(wǎng)絡上開始的。我偶然看到了這個討論會的論題,發(fā)生了興趣。本來周末的我一般是很懶的,沒什么事情是不會出門的。而當我看到這論題后,就給舉辦者發(fā)信表示愿意參加。于是,一個周六的下午,我就坐在了討論會的現(xiàn)場。參加完這個討論后,我覺得有必要把其中的精華部分寫下來,和網(wǎng)絡上的廣大程序員共享,于是就有了這篇文章。      二.主題:      編寫優(yōu)質(zhì)無錯的代碼-討論會主題。   &#

3、160;  相信每個程序員都有這種希望,誰都不愿意自己寫出來的代碼在release之后出錯,需要不停的修改維護。但是,主持人提出了這樣一個問題:"編寫優(yōu)質(zhì)無錯代碼是否必要?" 為什么呢?我稍微解釋一下。在項目的時間很      緊張的時候,是按期完成任務重要,還是代碼的穩(wěn)定性,優(yōu)質(zhì)無錯重要呢?      主持人提出的四個具體問題是:      1、編寫優(yōu)質(zhì)無錯的代碼的代價是什么?   &

4、#160;  2、代碼的質(zhì)量重要還是編寫效率重要?      3、在壓力的情況下,你會犧牲質(zhì)量來提高效率么?      4、編寫優(yōu)質(zhì)無錯的代碼是否意味著效率的降低?          對于第一個問題,編寫優(yōu)質(zhì)無錯代碼的代價當然是時間,不過隨著編程人員的經(jīng)驗逐漸豐富,所需要的時間也逐漸減少。對于第二個問題,代碼的質(zhì)量比編寫效率重要。當你花了1周時間寫出來的代碼需要你花一個月或者更長的時間去debug

5、, 去修改錯誤,這種效率的損失是得不償失的。對于第三個問題, 這需要看項目經(jīng)理或者產(chǎn)品經(jīng)理的態(tài)度和專業(yè)精神了。如果在一個專業(yè)的項目經(jīng)理或者產(chǎn)品經(jīng)理的指揮下,當然是首先保證質(zhì)量其次提高效率。而對于某些項目經(jīng)理或者產(chǎn)品經(jīng)理來說,按時完成任務是最重要的,他們往往不在乎在軟件發(fā)布之后花比開發(fā)時間長得多的時間去修改程序,維護錯誤。因為,對于他們來說,首先是要完成任務,好給上級領導交差,至于后期維護,就是另外一個任務了,維護花的時間多,正說明了他這個項目的復雜性和難度。而對于開發(fā)人員來講,所希望的則正好相反。開發(fā)人員不喜歡花太多的時間在一個爛攤子上。所以,在討論會上,大家紛紛表  &#

6、160;   示,應該讓項目經(jīng)理或者產(chǎn)品經(jīng)理也來聽一聽這個討論會:-)。      對于第四個問題,當然優(yōu)質(zhì)無錯代碼不是意味著效率的降低,而是正好相反,對提高效率有很好的促進作用。一個版本發(fā)布之后,如果因為錯誤太多,開發(fā)人員不得不去花很多時間修改bug, 甚至要從系統(tǒng)的體系結構方面去做      大的改動,重新編寫部分代碼,這種效率的降低才是更大,更不能承受的。而且,花了太多的時間在老版本的維護上,必然影響到新版本的工程進度,直接影響到整個產(chǎn)品線的質(zhì)量和進度,嚴重的甚至會毀掉

7、整個產(chǎn)品。      對于這一個主題,我的回答是,在時間允許的范圍之內(nèi),盡量提高代碼的質(zhì)量,不追求慢工出細活,不追求代碼的100%無錯,但是要保證99%以上的無錯。這樣,在時間的壓力下,在質(zhì)量要求的束縛下,就要求程序員有一個良      好的習慣,和穩(wěn)健的編程風格,以保證代碼的優(yōu)質(zhì)無錯。這就是第二個問題:什么是編寫優(yōu)質(zhì)無錯的代碼的核心思想?優(yōu)質(zhì)無錯是相對的,而不是絕對的。任何代碼,都不可能說是絕對無錯的,但是在絕大部分情況下,是穩(wěn)定的,強健的,優(yōu)質(zhì)的,無錯的。每次發(fā)布的時候,都會對上次的發(fā)布版本

8、做若干修改,增強功能的同時,也要修改若干bug。那么,核心思想就是:怎樣才能自動地查出這個錯誤。怎樣才能避免這個錯誤。      三.編寫優(yōu)質(zhì)無錯代碼的經(jīng)驗      在說了上面很多理論性的問題之后,來看一看具體問題。先來看一看一個具體的題目:(我本人就是先在網(wǎng)上看了這個題目,才對這個討論會發(fā)生興趣的)      題目1:      作為開發(fā)團隊的一員,你需要實現(xiàn)一些庫函數(shù)提供給其他人使用。假設你

9、實現(xiàn)的一個函數(shù)原型如下:      int DoSomeThing(char* pParam)            .            你們約定好參數(shù)pParam不能為NULL,但為了防止調(diào)用者錯誤傳遞NULL,你需要在你的函數(shù)里做判斷處理。      請問你會選擇那種方式,并說明原因?&#

10、160;     (a) if (!pParam)      return 0;      (b) if (!pParam)      return ERROR_PARAM;      (c) if (!pParam)      pParam = ""   &

11、#160;  .      (d) if (!pParam)      throw EXCEPTION_ERROR_PARAM;      (e) if (!pParam)      MessageBox(.);      (f) assert(!pParam);      (附加說明一點

12、,基于目前開發(fā)人員技術分布情況和參與討論會的人員的技術分布情況,這次所列舉的例子都是C/C+和Java方面的,不涉及到VB, PB, Delphi等語言。不過對于這些程序員,討論也是有借鑒作用的。)關于這個問題,大概是所有的程序員都會遇到的。所以,在網(wǎng)上和討論會上,都發(fā)生了激烈的爭論和意見交換。我大概把主要的幾種觀點記錄了一下,列舉在下面:      1、選擇f的理由      因為非NULL是約定,所以可以確定是調(diào)用者的問題,f可以明確地指出這一點,防止錯誤擴散。  

13、60;   我的附加說明: 防止錯誤擴散的意思是,如果用其他方式,比如throwexception的方式,這個異常不一定會在調(diào)用此函數(shù)的上一層被捕捉到,可能會被繼續(xù)拋出直到最上一層或者直到在某一層被catch到,這樣的話,錯誤就會距離發(fā)生地點很遠,擴散開來。這一觀點,代表了一大部分的程序員的觀點。      2、反對用f      不贊成assert, assert更重要的作用是程序體里面的一個注釋, 在閱讀程序的時候起作用不能依賴他來檢測錯誤, 很大程度上assert容易使

14、使用者依賴它本不應該依賴的東西。      這也代表了部分程序員的觀點,認為assert是不可依賴的,而應該依賴于錯誤檢測,比如返回值或者異常。      3、另外一種觀點      f和d都可取。如果沒有系統(tǒng)開銷的考慮,d則更好些??梢砸慌e兩得。如果沒人catch這個exception,其結果就跟f一樣,按bug處理,dump core留下一stack trace。如果有人catch,那就按運行錯誤處理.但是返回一特初值表示錯誤,只是將錯誤上交

15、,掩耳盜鈴而已。最終總得有個人assert,messagebox,throwexception,perror+exit,或別得什么的。既然已經(jīng)是約定,就干脆付起責任。      4、一種反對d的理由      不可用d, 這就像你用人,卻不相信人一樣,偏要try,catch防范他。其實那個錯是自己造成的,如果看到異常就容易不檢討自己。      5、關于觀點3的支持意見      討論過程中,有人

16、認為assert檢查的是bug, 而異常是可以恢復的意外情況。所以,觀點3的支持者說:可恢復的意外是可以理解的,但可恢復的bug就沒什么意義了。既然已經(jīng)約定好了,你再違背,就屬于是bug而不是意外了(比如打不開文件什么的)。很多庫函數(shù)都不檢查指針的合法性(除了系統(tǒng)調(diào)用以外,因為總不能讓系統(tǒng)dump core吧),也不檢查指針是否為NULL(因為如果層層都檢查,必定勞民傷財,干脆讓最上面調(diào)用的人在調(diào)用之外查)。      6、選擇d+f      選f+d, 好處如下:  &#

17、160;   a以最激烈的方式,充分暴露調(diào)用都的錯誤!能及時修改BUG      b便于調(diào)試,問題出現(xiàn)后,直接到事故現(xiàn)場。比120還快!      c對于realse版的代碼沒有任何副作用。      d以處理的代價來看 采用斷言也是編寫最小一種。      e它是多語種,多平臺所通用的方式, 如:C /C+ VB,Java1.4 在win ,unix通吃, 便于移置!

18、0;     如果在現(xiàn)實中,測試沒有能找到所有的BUG,那可能就要用異常來幫忙了!      當然,我也提出了我的觀點, 我支持觀點6。理由如下:      assert只在debug標志的時候有用,而在編譯release版本的時候不起作用。assert對于檢查硬編碼的錯誤,是非常有用的,能夠及時的查處編碼的錯誤。比如borland c+的類庫源代碼中就有很多這樣的assert。但是assert     

19、不是萬能的,因為有很多錯誤的發(fā)生不是完全在編譯時發(fā)生的,而是運行時的錯誤。在release后,assert是不可能依賴的。那么,我們就需要exception這一機制來檢測運行時錯誤,并相應的做出處理。當然,在異常檢測和處理過程中還有許多需要討論的問題,由于不是這一題目的范圍,我們沒有必要繼續(xù)討論得太多,但是,提出來希望大家注意:異常不是捕獲了就完成任務了,而要對于不同的情況,采取不同的處理辦法,千萬不能只是捕獲,而不做任何處理,那樣和不捕獲異常沒有任何區(qū)別。      在題目剛剛提出的時候,選擇各種答案的人都有,所以,我有必要在這里把其他答案為

20、什么不能選的理由說一下。      (a) if (!pParam)      return 0;      這是很多初級程序員常常采取的一種方式。返回值設為0。 因為函數(shù)的返回值往往是計算的結果,不贊成把錯誤標志值和計算結果混在一起使用,容易造成使用者的誤會。當然,在很多unix函數(shù)中,由于歷史原因,還存在很多這樣子的函數(shù),所以需要指出,不要沿用這種方式。      (b) if (!pPara

21、m)      return ERROR_PARAM;      b比a稍微好一點點,返回了一個常量或者預定義的宏。 從返回值的字面上,調(diào)用者能知道發(fā)生了什么錯誤,但是,這也不是一種好的方法。      (c) if (!pParam)      pParam = ""      .    

22、;  這是最不好的方式。直接給pParam賦予空字符串,然后繼續(xù)函數(shù)過程,這容易造成不可預料的后果,是程序不穩(wěn)定的根源。      (d) if (!pParam)      throw EXCEPTION_ERROR_PARAM;      拋出異常,剛剛已經(jīng)討論過了,不再贅述。      (e) if (!pParam)      M

23、essageBox(.);      這是一種比較可笑的方式,當然也有不少人用。MessageBox是直接彈出一個對話框,告訴使用者,出錯了。但是并不做任何處理,程序繼續(xù)往下執(zhí)行,直到出錯崩潰。呵呵      (f) assert(!pParam);      斷言,剛剛已經(jīng)討論過了,不再贅述。      以上這個題目,引發(fā)了所有與會者的興趣,討論異常熱烈,最后,主持人也給出了自己的觀點:d+f。

24、當然這并不是標準答案,因為編程這一門課程本來就沒有什么標準答案,大家見仁見智,這個答案只是經(jīng)驗的積累。      主持人緊接著列出了"編寫優(yōu)質(zhì)無錯代碼的經(jīng)驗":      a.理想的編譯器和實際的編譯器      b.使用斷言      c.函數(shù)的界面設計      d.考慮風險    &

25、#160; e.態(tài)度的問題      以上是本節(jié)的主要內(nèi)容。斷言,剛剛的問題中已經(jīng)討論過了,來看看其他的內(nèi)容。      理想的編譯器和實際的編譯器:      題目二:      下面memcpy函數(shù)實現(xiàn)有什么問題:      Void *memcpy(void *pvTo,void *pvFrom,size_t size)  

26、;    byte *pbTo=(byte *) pvTo;      byte *pbFrom=(byte *)pvFrom;      while(size - >0);      *pbTo+= *pbFrom+;      return pvTo;          

27、;  呵呵,粗略一看,這函數(shù)還真找不出問題來。但是仔細看看,你就會發(fā)現(xiàn)while(size - >0);      這里多了一個分號,導致下面的*pbTo+= *pbFrom+;不是在while循環(huán)中執(zhí)行多次,而是只執(zhí)行了一次。當然這不是函數(shù)設計者的預期結果,而編譯器卻不會報告錯誤,因為while(size - >0);從語法上來講,并沒有錯誤。這就是理想的編譯器和實際的編譯器的區(qū)別所在。      那么,該怎么檢查這種錯誤呢?主持人提出了如下辦法:  

28、    while(size - >0) NULL; 可以加入NULL來解決空語句. 這樣子,當你需要while(size - >0)        *pbTo+= *pbFrom+;      這種形式的時候,就不會發(fā)生錯誤了,只需要用眼睛看看,就能發(fā)現(xiàn)了。兩點好處 1 無冗余代碼,2 使人更明白。減少風險.      還有人會這么寫    &

29、#160; if( (n=read(.) = 1) .      在這里,賦值符號=和判斷相等的符號=容易敲錯,而編譯器又檢查不出來,可能就會有如下錯誤:      If(ch = ).;這也是需要注意的問題。      理想的編譯器和實際的編譯器小結:      a.把屢次出錯的合法的C習慣用法看成程序中的錯誤      b.增強編譯器的警告級別

30、      c.使用其它的工具來檢查代碼 如 Lint 等      d.進行單元測試      e.消除程序錯誤的最好方法是盡可能早、盡可能容易地發(fā)現(xiàn)錯誤,要尋求費力最小的自動查錯的方法      f.努力減少程序員查錯所需的技巧      使用斷言      題目三  

31、60;   下面函數(shù)實現(xiàn),哪一個好,為什么?      a.      char Uptolower(char ch)      if(ch >= A && ch <= Z)      return ch+=a-A;      return -1;    

32、60;       b.      char Uptolower(char ch)      assert(ch >= A && ch <= Z);      if(ch >= A && ch <= Z)      return ch+=a-A;    

33、  return ch;            c.      char Uptolower(char ch)      assert(ch >= A && ch <= Z);      return ch+(a-A);        

34、60;   分析:      a.該函數(shù)檢查ch是否在A.Z之間,如果是,則返回相應的小寫字符,如果不是,則返回-1。      缺點在于:把錯誤標志值和計算結果混在一起使用,容易造成使用者的誤會。      b.該函數(shù)使用了斷言,如果ch在A.Z之間則返回相應的小寫字符,如果不是,斷言會起作用,程序發(fā)生錯誤并退出。而最后一個return ch;則是在release的時候,如果不是A.Z之間,則返回原來的字符。但是,從書寫效率

35、上來說,這個函數(shù)稍微羅嗦了一點。因為它重復使用了斷言和if判斷。      c.該函數(shù)也使用了斷言,返回相應大寫字母的小寫字母。      使用斷言的好處:      a.暴露了調(diào)用者的錯誤      b.便于調(diào)試      c.對代碼沒有代價      d.最少的處理代價  &

36、#160;   斷言使用舉例:      void memcpy(void * pvTo,void *pvFrom,size_t size)      void *pbTo= (byte *)pvTo;      void *pbFrom= (byte * pvFrom);      assert(pvTo !=NULL && pvFrom !=NULL);&#

37、160;     assert(pbTo >= pbFrom +size' 'pbFrom >= pbTo+size);                  使用斷言的規(guī)則:      a.要使用斷言對函數(shù)參數(shù)進行確認      b.要從程序中刪去無定義的特性或者在程序中使 用斷言來

38、檢查出無定義特性的非法使用      c.不要浪費別人的時間-詳細說明不清楚的斷言      d.消除所做的隱式假定,或者利用檢查其正確性      e.在進行防錯性程序設計時,不要隱瞞錯誤防錯性程序設計雖然被譽為有較好的編碼風格,但它卻隱瞞了錯誤。      要記住,我們正在談論的錯誤決不應該再發(fā)生,而對這些錯所進行的安全處理又編寫無錯代碼變得更加困難   

39、0;  f.要利用不同的算法對程序的結果進行確認      g.不要等待錯誤發(fā)生,要使用初始檢查程序      斷言小結:      a.要同時維護交付和調(diào)試兩個版本。封裝交付的版本,應盡可能地使用調(diào)試版本進行自動查錯。      b.斷言是進行調(diào)試檢查的簡單方法。要使用斷言捕捉不應該發(fā)生的非法情況。不要混淆非法情況與錯誤情況之間的區(qū)別,后者是在最終產(chǎn)品中必須處理的。 

40、0;    c.使用斷言對函數(shù)的參數(shù)進行確認,并且在程序員使用了無定義的特性時向程序員報警。涵數(shù)定義得越嚴格,確認其參數(shù)就越容易。      d.防錯性程序設計會隱瞞錯誤。在進行防錯編碼時,如果”不可能發(fā)生”的情況確實發(fā)生了,要使用斷言進行報警。      寫到這里,我們初步探討了編寫優(yōu)質(zhì)無錯代碼的必要性,原則,和相關經(jīng)驗。      留幾個練習題目,大家也參與一下討論吧。   

41、0;  練習題目1:      下面的memset函數(shù)實現(xiàn)有什么問題?      void *memset(void *pv, byte b, size_t size)            byte *pb = (byte *)pv;      unsigned long l;     

42、 size_t sizeSize;      l = (b << 8) | b; /* 用4個字節(jié)拼成一個long */      l = (l << 16) | l;      pb = (byte *)longfill(long *)pb, l, size/4);      size = size % 4;      w

43、hile (size- > 0)      *pb+ = b;      return (pv);            練習題目2:      下面的代碼用memset將三個局部變量置為0,請問可能會有什么問題?      void DoSomeThing(.)  

44、60;         int i;      int j;      int k;      memset(&k, 0, 3*sizeof(int); / 將i,j,k置為0      .            練習題目

45、3:      定義結構如下:      typedef struct            char c1;      char c2;      int n;      stru;      請問

46、sizeof(stru)等于多少?并說明理由。      練習題目4:      下面是C語言中兩種if語句判斷方式。請問哪種寫法更好?為什么?      int n;      if (n = 10) / 第一種判斷方式      if (10 = n) / 第二種判斷方式      練習題目5:

47、      下面的代碼有什么問題?      void DoSomeThing(.)            char* p;      .      p = malloc(1024); / 分配1K的空間      if (NULL = p)

48、0;     return;      .      p = realloc(p, 2048); / 空間不夠,重新分配到2K      if (NULL = p)      return;      .         

49、0;  練習題目6:      下面的代碼有什么問題?      char *DoSomeThing(.)            char str16;      .      return str;        &#

50、160;   練習題目7:      下面的代碼有什么問題?      char *_strdup( const char *strSource )            static char strMAX_STR_LEN;      strcpy(str, strSource);    

51、;  return str;            練習題目8:      下面的代碼有什么問題?并請給出正確的寫法。      try      FILE* fp = fopen("c:1.dat");      if (NULL != fp)  

52、          .            fclose(fp);            except(EXCEPTION_EXECUTE_HANDLER)      編寫優(yōu)質(zhì)無錯的代碼(幻燈片完全版)http:/LinuxA 01-08-19 21:59 549p

53、ariesram-      介紹      編寫優(yōu)質(zhì)無錯代碼是否必要?      編寫優(yōu)質(zhì)無錯的代碼的核心思想      編寫優(yōu)質(zhì)無錯代碼的經(jīng)驗      概述      概述各個主題      解釋各個單獨的主題如何組合在一起 

54、0;    編寫優(yōu)質(zhì)無錯的代碼是否必要 ?      編寫優(yōu)質(zhì)無錯的代碼的代價是什么?      代碼的質(zhì)量重要還是編寫效率重要?在壓力的情況下,你會犧牲質(zhì)量來提高      效率么?      編寫優(yōu)質(zhì)無錯的代碼是否意味著效率的將低 ?      編寫優(yōu)質(zhì)無錯的代碼的核心思想   

55、60;  大家是否為提高代碼編寫代碼質(zhì)量而努力?      習題      怎樣才能自動地查出這個錯誤!      怎樣才能避免這個錯誤!      編寫優(yōu)質(zhì)無錯代碼的經(jīng)驗      理想的編譯器和實際的編譯器      使用斷言     

56、 函數(shù)的界面設計      考慮風險      態(tài)度的問題      Void *memcpy(void *pvTo,void *pvFrom,size_t size)      byte *pbTo=(byte *) pvTo;      byte *pbFrom=(byte *)pvFrom;    &#

57、160; while(size - >0);      *pbTo+= *pbFrom+;      return pvTo;            在判斷中使用無意的賦值。 If(ch = );      解決的辦法:1wile () NULL; 可以加入NULL來解決空語句 ;     

58、2 if ( =ch);      (strcpy函數(shù)的例子) while(*pchTo += *pchForm +) NULL;      while(*pchTo+=*pchFrom+)!=) NULL;      兩點好處 1 無冗余代碼,2 使人更明白。減少風險.      把屢次出錯的合法的C習慣用法看成程序中的錯誤      增強編譯器

59、的警告級別      使用其它的工具來檢查代碼 如 Lint 等      進行單元測試      小結:      消除程序錯誤的最好方法是盡可能早、盡可能容易地發(fā)現(xiàn)錯誤,要尋求費力      最小的自動查錯的方法      努力減少程序員查錯所需的技巧   

60、0;  使用斷言      Char Uptolower(char ch)      if(ch >= A && ch <= Z)      return ch+=a-A;      return -1;            Char Uptolower(ch

61、ar ch)      assert(ch >= A && ch <= Z);      if(ch >= A && ch <= Z)      return ch+=a-A;      return ch;            Char U

62、ptolower(char ch)      assert(ch >= A && ch <= Z);      return ch+(a-A);            暴露了調(diào)用者的錯誤      便于調(diào)試      對代碼沒有代價   &#

63、160;  最少的處理代價      void memcpy(void * pvTo,void *pvFrom,size_t size)      void *pbTo= (byte *)pvTo;      void *pbFrom= (byte * pvFrom);      assert(pvTo !=NULL && pvFrom !=NULL); 

64、60;    assert(pbTo >= pbFrom +size' 'pbFrom >= pbTo+size);                  要使用斷言對函數(shù)參數(shù)進行確認      要從程序中刪去無定義的特性或者在程序中使 用斷言來檢查出無定義特性的      非法使用 

65、     不要浪費別人的時間-詳細說明不清楚的斷言      消除所做的隱式假定,或者利用檢查其正確性      在進行防錯性程序設計時,不要隱瞞錯誤      防錯性程序設計雖然被譽為有較好的編碼風格,但它卻隱瞞了錯誤。要記住,      我們正在談論的錯誤決不應該再發(fā)生,而對這些錯所進行的安全處理又編寫    &#

66、160; 無錯代碼變得更加困難      要利用不同的算法對程序的結果進行確認      不要等待錯誤發(fā)生,要使用初始檢查程序      斷言的使用與防錯的程序設計沖突么?他們相適應的范圍環(huán)境在什么呢?      斷言小結:      要同時維護交付和調(diào)試兩個版本。封裝交付的版本,應盡可能地使用調(diào)試版    

67、  本進行自動查錯。      斷言是進行調(diào)試檢查的簡單方法。要使用斷言捕捉不應該發(fā)生的非法情況。      不要混淆非法情況與錯誤情況之間的區(qū)別,后者是在最終產(chǎn)品中必須處理的。      使用斷言對函數(shù)的參數(shù)進行確認,并且在程序員使用了無定義的特性時向程      序員報警。涵數(shù)定義得越嚴格,確認其參數(shù)就越容易。      防錯性程序設

68、計會隱瞞錯誤。在進行防錯編碼時,如果”不可能發(fā)生”的情況      確實發(fā)生了,要使用斷言進行報警。      函數(shù)的界面      Char *strdup(char *str)      Char * strNew;      strNew = (char *) maloc (strlen(str)+1);   &

69、#160;  Strcpy(strNew,str);      Return (strNew);            Char c ;      c=getchar();      if(EOF=c)      .      void s

70、trdup(const char* strsrc , char * strdes, size_t dessize );      Bool getchar(char * pch);      要使用不容易忽視錯誤情況,不要在返回值中隱藏錯誤代碼      void * realloc (void * pv , size_t size ); 是一個面面俱到的函數(shù)      realloc() cha

71、nges the size of the memory block pointed to by ptr      to size bytes. The contents will be unchanged to the minimum of      the old and new sizes; newly allocated memory will be      uninitialized. If ptr is NULL, the call

72、is equivalent to      malloc(size); if size is equal to zero, the call is equivalent      to free(ptr). Unless ptr is NULL, it must have been returned by an      earlier call to malloc(), calloc() or realloc().  

73、60;   不要編寫多種功能集于一身的函數(shù)      void *memset( void *dest, int c, size_t count );      size_t count=10;      int setvalue=0xff;      memset(pdest,count,setvalue);      cha

74、r *copysubstr (char * strTo, char * strFrom , size_t size)            char * strStar= strTo;      ASSERT(size<=strlen(strFrom);            我的寫法:Void memset( void *dest, byt

75、e c, size_t count );      不要模棱兩可,要明確地定義函數(shù)的參數(shù)。      編寫函數(shù)使其在給定有效的輸入情況下不會失?。╰olower函數(shù))      函數(shù)界面小結      設計能夠低御錯誤的界面并不困難,但這確實需要多加考慮并且愿意放棄      根深蒂固的編碼習慣。 只需簡單地改變函數(shù)的界面,就可以使 程序員編

76、60;     寫出正確的代碼。 關鍵概念是”盡可能地使一切清晰明了”。      最容易使用和理解的函數(shù)界面,是其中每個輸入和輸出參數(shù)都只代表一種      類型數(shù)據(jù)的界面。把錯誤碼值和其它的專用值混在函數(shù)的輸入和輸出參數(shù)      中,只會搞亂函數(shù)的界面。      設計函數(shù)的界面迫使程序員考慮所有重要細節(jié)(如錯誤情況的處理),不  

77、    要使 程序員能夠很容易地忽視或者忘記有關的細節(jié)。      老要想到程序員調(diào)用所編函數(shù)的方式,找出可能使程序員無意引入錯誤碼      的界面缺陷。尤其重要的是要爭取編出永遠成功的函數(shù),使調(diào)用者不必進      行相的錯誤處理。      為了增加程序的或理解性從而減少錯誤,要保證所編函數(shù)的調(diào)用能夠被必     

78、; 須閱讀這些調(diào)用的程序員所理解。莫明其妙的數(shù)字和布爾參數(shù)都與這一目      標背道而馳,因此應該給以消除。      分解多功能的函數(shù).取更專業(yè)的函數(shù)名不但可以增進人們對它理解,而且      使我們可以更加嚴格的斷言自動地檢查出調(diào)用錯誤      為了向程序員展示出所編函數(shù)的適當調(diào)用方法,要在函數(shù)的界面中通過注      解的方式詳細說明。要

79、強調(diào)危險的方面 。      考慮編寫代碼的風險      如何做才能減少甚至消除風險      程序員忽視風險性。      肓目認為,自已的程序不會錯誤。程序員不會打算出錯。出錯后,也不吃      驚。      思想上有,不管作出哪種選擇,最后總能得到無錯代碼。  

80、60;   Long 的位域有多長,ANSI并沒有對些做出標準      使用有嚴格定義的數(shù)據(jù)類型 int32 ,_int64,_int16 (windows)      數(shù)據(jù)上溢與下溢      #define Max=255;      unsigned char ch      for(ch =0 ; ch <=Ma

81、x; ch+)                   經(jīng)常反問自己: “這個變量或表達式會上溢或下溢嗎?”      一個”任務”應一次完成      每個函數(shù)只完成它自己的任務      函數(shù)要符合它的設計原則:高內(nèi)聚, 有且只有一個任務。     

82、 違反原則,難以調(diào)試,測試等。難以閱讀。代碼難以重復利用      “?:” 運算符也是一種if 語句      使用 “?:” 運算符所存在的問題是:由于它很簡單,容易使用,看起來好象      是產(chǎn)生高效代碼的理想方法,因此程序員就不再尋找更好的解決方法了。更      嚴重的是,程序員會將if 版本轉(zhuǎn)換為 “? :”      unsigne

83、d uCycleCheckBox(unsigned uCur)      reurn (uCur<=1)? (uCur=1)? 2: (uCur+1);            避免使用嵌套的“? :”運算符      每種特殊情況只能處理一次。      (C+的異常處理,結構化異常處理,以及Java 中的機制 finally) &

84、#160;    避免使用有風險的語言慣用語      在某些程序員看來,放棄任何可能獲得效率的機會似乎犯罪。要樹立:即使效      率可能會稍稍低一點,也要使用安全的設計和實現(xiàn)來系統(tǒng)地減少風險性。      a=a+c/4 為變成 a=a+c>>2;      不一致性是編寫正確代碼的障礙。     

85、急于改正的心里,在沒有規(guī)約的情況下,會造成很大的混亂。比起沒有改進造      成了更大的損失。      編碼風格如此,錯誤處理如此;      避免調(diào)用返回錯誤的函數(shù)      在設計函數(shù)時盡量避免返回錯誤值,以免程序員錯誤地處理或漏掉這些返回值      風險小結      在選擇數(shù)據(jù)類型的時

86、候要謹慎。      由于代碼可能會在不理想的硬件上運行,因此很可能算法是正確的而執(zhí)行起來      卻有錯。所以要經(jīng)常詳細檢查計算結果和測試結果的數(shù)據(jù)類型范圍是否上溢或      下溢。      每函數(shù)應該只有一個嚴格定義的任務,不僅如此,完成每個任務也應只有一種      途徑。      If 語句是個警告信號,說明代碼所做的工作可能比所需要的要多。努力消除代      碼中每一個不必要的if 語句,經(jīng)常反問自己:”怎樣改變設計從而刪掉這個特      殊

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論