• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            woaidongmao

            文章均收錄自他人博客,但不喜標題前加-[轉貼],因其丑陋,見諒!~
            隨筆 - 1469, 文章 - 0, 評論 - 661, 引用 - 0
            數據加載中……

            64位開發中去除64位平臺的內存錯誤方法

               對新平臺上應用程序的開發者來說,64位平臺的穩定和可靠,是吸引他們的關鍵;而任何內存錯誤問題都會導致開發工作的失敗,內存錯誤最棘手之處在于它是難以捉摸的,找出它們非常困難且要花費大量時間。內存錯誤不會在通常意義上的測試中暴露出來,正是因為它們潛在的有害性,所以在程序定型之前,去除所有的內存問題就顯得非

             

            常必要了。

              目前有一些強大的內存錯誤檢測工具,它們可以在運行于雙核心處理器的應用程序中,找出導致線程內存錯誤的原因;它可在傳統測試技術找不出問題的地方,找出并修正那些難以捉摸、導致程序崩潰的"元兇"。錯誤檢測工具可幫助你在發布程序之前,找出并修正那些C/C++內存錯誤,而在移植程序之前修正這些問題,可提高在新平臺新架構上的程序質量,使移植過程更加流水線化,并且使老程序更加健壯可靠。

              為何移植如此之難?

              在向64位處理器或新硬件移植代碼時產生的問題當中,大多數開發者是負有主要責任的。就此來說,代碼在移植到新平臺或新架構之上時,內存問題似乎也成倍增長了。

              在過渡到64位架構時最基本的問題,就是對各種不同的int和指針在比特位長度上假定。在從long轉換到int時,不管是賦值還是顯式轉換,都存在著一定的隱含限制。前者可能產生一個編譯器警告,而后者可能被無聲地接受,就此導致了運行時的各種錯誤。另一個問題就是int常量并不總是與int同樣大小,這是混淆有符號和無符號常量的問題,同時,適當地使用有關的后綴可以減少此類問題的發生。

              另一些問題的主要原因是各種指針類型的不匹配。舉例來說,在多數64位架構上,指針類型不能再放入一個int中,而那些把指針值儲存在int變量中的代碼,此時當然就會出錯了。

              這些問題通常會在移植過程中暴露出來,因為移植從本質上來說是一種變體測試。當你在移植代碼時,實際上是在創建一種"同等變體"(對原始代碼的小幅改動,不會影響到測試的結果),而通過這些"同等變體",可找出許多不常見的錯誤。在C/C++中,創建和運行"同等變體",可揭示出以下問題:

              1、缺少拷貝構造函數或錯誤的拷貝構造函數

              2、缺少或不正確的構造函數

              3、初始化代碼的錯誤順序

              4、指針操作的問題

              5、依賴未定義的行為,如求值的順序

              在準備移植應用程序時,有以下幾個相關步驟

              第1步、在移植之前,要保證原始代碼中沒有諸如內存崩潰、內存泄露等問題,找出指針類型和int錯誤的最有效的一個方法是,采用平衡變體測試,來達到運行時錯誤檢測的目的。

              變體測試最先是為解決無法計量測試的準確性問題而產生的,大致如下:假定已有了一個完美的測試方案,它已經覆蓋了所有的可能性,再假定已有一個完美的程序通過了這個測試,接下來修改代碼(稱之為變異),在測試方案中運行這個"變異"后的程序(稱之為變體),將會有兩個可能的情況:

              一是程序會受代碼改變的影響,并且測試方案檢測到了,在此假定測試方案是完美的,這意味著它可以檢測一切改變。此時變體被稱作"已死的變體"

              二是程序沒受改變的影響,而測試方案也沒有檢測到這個變體。此時變體稱作"同等變體"

              如果拿"已死變體"和已生成的變體作對比,就會發現這個比率要小于1,這個數字表示程序對代碼改變有多敏感。事實上,完美的測試方案和完美的程序都不存在,這就說上面的兩種情況可能會有一個發生。

              程序受影響的結果因個體而異,如果測試方案不適當,將無法檢測到。"已經變體""生成變體"的比率小于1同時也揭示了測試方案有多精確。

              在實踐中,往往無法區分測試方案不精確與同等變體之間的關系。由于缺乏其他的可能性,在此我們只好把"已死變體"對所有變體的比率,看成是測試方案的精確程度。

              例1test1.c)證實了以上的說法(此處所有的代碼均在Linux下編譯),test1.c用以下命令編譯:

             

            cc -o test1 test1.c.

            main(argc, argv) /* line 1 */
            int argc; /* line 2 */
            char *argv[]; /* line 3 */
            { /* line 4 */
            int c=0; /* line 5 */
            /* line 6 */
            if(atoi(argv[1]) < 3){ /* line 7 */
            printf("Got less than 3\n"); /* line 8 */
            if(atoi(argv[2]) > 5) /* line 9 */
            c = 2; /* line 10 */
            } /* line 11 */
            else /* line 12 */
            printf("Got more than 3\n"); /* line 13 */
            exit(0); /* line 14 */
            } /* line 15 */


              例1:程序test1.c

              這個簡單的程序讀取輸入的參數,并打印出相關的信息。現在假定用一個測試方案來測試此程序:

            Test Case 1:
            input 2 4
            output Got less than 3
            Test Case 2:
            input 4 4
            output Got more than 3
            Test Case 3:
            input 4 6
            output Got more than 3
            Test Case 4:
            input 2 6
            output Got less than 3
            Test Case 5:
            input 4
            output Got more than 3


              這個測試方案在業界是有一定代表性的,它進行正則測試,表示它將測試對所有正確的輸入,程序是否有正確的輸出,而忽視非法的輸入。程序test1完全通過測試,但它也許隱藏著嚴重的錯誤。

              現在,對程序進行"變體",用以下簡單的改變:

            Mutant 1: change line 9 to the form
            if(atoi(argv[2]) <= 5)
            Mutant 2: change line 7 to the form
            if(atoi(argv[1]) >= 3)
            Mutant 3: change line 5 to the form
            int c=3;


              如果在測試方案中運行此修改后的程序,Mutants 13完全通過測試,而Mutant 2則無法通過。

                Mutants 13沒有改變程序的輸出,所以是同等變體,而測試方案沒有檢測

             

            到它們。Mutant 2不是同等變體,故Test Cases 1-4將會檢測到程序的錯誤輸出,而Test Case 5在不同的電腦上可能會有不同的表現。以上表明,程序的錯誤輸出,可看作是程序可能會崩潰的一個信號。

              我們統計一下,共創建了三個變體,而只被發現了一個,這說明表示測試方案的質量為1/3,正如你看到的,1/3有點低,之所以低是因為產生了兩個同等變體。這個數字應當作是測試不足的一個警告,實際上,測試方案應檢測到程序中的

             

            兩個嚴重錯誤。

              再回到Mutant 2,在Test Case 5中運行它,如果程序崩潰了,那這個變體測試不但計量到了測試方案的質量,還檢測到了嚴重的錯誤,這就是變體測試發現錯誤的方法。

            main(argc, argv) /* line 1 */
            int argc; /* line 2 */
            char *argv[]; /* line 3 */
            { /* line 4 */
            int c=0; /* line 5 */
            int a, b; /* line 6 */
            /* line 7 */
            a = atoi(argv[1]); /* line 8 */
            b = atoi(argv[2]); /* line 9 */
            if(a < 3){ /* line 10 */
            printf("Got less than 3\n"); /* line 12 */
            if(b > 5) /* line 13 */
            c = 2; /* line 14 */
            } /* line 15 */
            else /* line 16 */
            printf("Got more than 3\n"); /* line 17 */
            exit(0); /* line 18 */
            } /* line 19 */


              例2:同等變體

              在例2中的同等變體(Mutant 4),它和前一個變體的不同之處在于,Mutant 4是同等變體,這意味著它在構建時的目的,就是要使修改后的程序如同原始程序一樣運行。如果在測試方案中運行Mutant 4,那么Test Case 5大概會失敗--程序將崩潰。此處表明,通過創建一個同行變體,實際上是增強了測試方案的檢測力度,由此得出的結論是,有以下兩種方法,可提高測試方案的精確性:

              ·在測試方案中增加測試數量

              ·在測試方案中運行同等變體

              這兩點是非常重要的,尤其是第二點,因為它證明了變體可提高測試的有效性。在這些例子中,是由手工創建了每一個變體,并且對每一個程序都作了單獨的修改,這個步驟費時又費力,但是自動生成同等變體是有可能的,正如例3所演示的,這個程序沒有輸入,只有一個輸出,原則上來說,它只需要一次測試:

            int doublew(x)
            int x;
            { return x*2; }

            int triple( y)
            int y;
            { return y*3; }

            main() {
            int i = 2;
            printf("Got %d \n", doublew(i++)+ triple(i++));
            }


              例3:自動生成變體

            Test Case 1:
            input none
            output 12


              有意思的是,這個程序因編譯器的差異,而分別給出答案1312(注:譯者在Visual C++ 2005中,得出的結果是10)。假設你要編寫一個這樣的程序,還要能在兩個不同的平臺上運行,如果不同平臺上的編譯器有所差異,此時你會察覺到這個程序的不同,疑問由此而生:"是哪錯了?"這有可能就是導致問題產生的原因。

              試想你在例4中創建了一個同等變體,此時這個程序的結果不依賴于編譯器,實際上應是13,這也是在預料之中的。但一旦運行變體測試,就會發現錯誤了。

            int doublew(x)
            int x;
            { return x*2; }

            int triple( y)
            int y;
            { return y*3; }

            main() {
            int i = 2;
            int a, b;

            a = doublew(i++);
            b = triple(i++);
            printf("Got %d \n", a+b);
            }


              例4:一個變體

              在變體測試中,最讓人驚奇的是,它能找出正常看來是不可能檢測到的錯誤,通常,這些錯誤隱藏得很深,直到程序崩潰時,才可能發現,但對此,程序員經常不能理解。同等變體是找出錯誤的機會,而不是其他。但普遍來說,程序員期望同等變體能得出與原程序一樣的結果,但如果總是這樣的話,那同等變體是沒有任何作用了。

              第2步:當清除最致命的錯誤之后,要把那些可能會出錯的代碼在移植之前,用靜態分析工具再確認一遍。在靜態分析時,有兩個主要的工作要做:

              ·找出并修正那些移植到新平臺之后可能會出錯的代碼

              ·找出并修正那些可能不能很好地被移植的代碼

                首先,要用業界推薦的C/C++編碼標準來檢查那些可能在新平臺上出錯的代碼,以確認其編碼結構沒有問題。通過確認代碼符合編碼標準,可防止不必要的錯誤發生,還能減少在新平臺上的調試工作量,并降低在最終產品中出現bug的機率。

              以下是一些可用的編碼標準:

              不要返回對一個局部對象或對在函數內用"new"初始化的指針

             

            的引用。對一個局部對象返回一個引用,可能會導致堆棧崩潰;而返回一個對在函數內用"new"初始化的指針的引用,可能會引起內存泄漏。

              不要轉換一個常量到非常量。這可能會導致數值被改變,從而破壞數據的完整性。這也會降低代碼的可讀性,因為你不能再假定常量不被改變。

              如果某個類有虛擬成員函數,它最好也帶有一個虛擬析構函數。這能在繼承類中防止內在泄漏。帶有任何虛擬成員函數的類,通常被用作基類,此時它應有一個虛擬析構函數,以保證繼承類通過一個指向基類的指針來引用時,相應的析構函數會被調用。

              公共成員函數必須為成員數據返回常量句柄。當把一個非常量的句柄提供給成員數據時,此時調用者可在成員函數之外修改成員數據,這就破壞了類的封裝性。

              不要把指向一個類的指針,轉換成指向另一個類的指針,除非它們之間有繼承關系。這種無效的

             

            轉換將導致不受控的指針、數據崩潰等問題,或者其他錯誤。

              不要從一個構造函數中直接訪問一個全局變量。C++語言的定義之中,沒有規定在不同的代碼單元中定義的靜態對象初始化的順序。因此,在從一個構造函數中訪問一個全局變量時,這個變量可能還沒有初始化。

              當找到并修正有錯誤的代碼之后,從那些在當前平臺上運行良好的代碼中再繼續找,因為它們可能不能被很好地移植。以下是一些對大多數64位移植項目都適用的規則:

              盡量使用標準類型。比如說,使用size_t而不是int。如果想要一個無符號的64int,那么請使用uint64_t。這個習慣不但有助于找出和防止代碼中的bug,還能在將來向128位處理器移植程序時,幫上大忙。

              檢查現有代碼中long數據類型的用法。如果變量、域、參數中數值的變化范圍,只在2Gig-1-2Gig4Gig0之間,那么最好分別使用int32_tuint32_t

              檢查所有的"窄向"賦值。應該避免這種情況出現,因為把一個long賦值給一個int,在64位數值上會導致截斷。

              找出"窄向"轉換。應只在表達式中使用窄向轉換,而不是在操作數中。

              找出那些把long*轉換成int*,或把int*轉換成long*的地方。在32位環境下,這也許是可交替的,但在64位中不行,并檢查所有的不匹配指針賦值。

              找出那些在乘法符號的兩端,沒有long操作數的表達式。要使int型表達式將產生64位結果,至少其中的一個操作數是longunsigned long

              找出long型值用int初始化的地方。應避免這種類型的初始化,因為甚至在64位類型的表達式中,int常量也可能只是代表一個32位類型。

              找出那些對int進行移位操作,又把結果賦給long的地方。如果結果是64位值,最好使用64位乘法。

              找出那些64位表達式中的int常量。在64位表達式中應使用64位值。

              找出把指針轉換成int的地方。涉及指針與int互轉換的代碼,應仔細檢查。

              檢查內聯匯編語句。因為它不可能被很好地移植。

              第3步:重復一遍運行時錯誤檢測,以確認所有的修改都沒有引入新的運行時錯誤。

              第4步:此時,你可選擇進行更多的測試步驟,以保證在移植之前,所有的代碼都完全正確。這個額外的步驟是單元測試,單元測試是在每一個軟件單元完成之后進行的傳統測試,它在開發階段的后期,也是有益的。因為在單元級別,很容易設計出每個函數的輸入,它將有助于更快地找出那些在應用級別測試中無法發現的錯誤。

              找出64位處理器上的問題

              也許64位處理器本身就有問題,如果是這樣的話,下面的步驟應該有用: 第1步:在64位處理器上重新編譯應用程序。在編譯中如果有問題,應考慮是不是因編譯器的不同而產生的。

              第2步:一旦重新編譯代碼,應進行代碼檢查,以確保新代碼都遵循適當的編碼標準。在這一點上,任何人都不希望每一次修改都帶來一個錯誤,此時解決好過在程序運行時才發現。

              第3步:鏈接并生成應用程序。

              第4步:應試著運行程序。如果在64位處理器上,運行程序時發現了問題,應使用單元測試方法一個函數一個函數地去找,這樣能確定哪些代碼沒有正確地被移植;修正這些問題直到程序可以運行。

              第5步:重復運行時錯誤檢測。

              一旦程序可以運行,一定要重復一遍運行時錯誤檢測,因為移植過程很可能導致新的問題產生,例如新的內存崩潰或程序工作方式有所不同。如果運行時錯誤檢測發現了錯誤,那么此時趕快修正它。

              結論

              遵循此文中提及的方法,可在程序發布之前,找到并修正C/C++內存錯誤,并可以節省下數周的調試時間,使用戶免受"災難"之苦。

             

            posted on 2009-09-08 00:35 肥仔 閱讀(2328) 評論(6)  編輯 收藏 引用 所屬分類: Windows開發

            評論

            # re: 64位開發中去除64位平臺的內存錯誤方法  回復  更多評論   

            Lots of specialists claim that <a href="http://lowest-rate-loans.com/topics/mortgage-loans">mortgage loans</a> aid people to live their own way, just because they can feel free to buy needed things. Moreover, various banks give credit loan for all people.
            2010-06-30 07:34 | JuanitaGoodwin34

            # re: 64位開發中去除64位平臺的內存錯誤方法  回復  更多評論   

            Lots of college students become embarrassed because of academic papers composing. However, clever people order coursework online and have advantages.
            2010-07-06 21:09 | buy coursework online

            # re: 64位開發中去除64位平臺的內存錯誤方法  回復  更多評論   

            Your knowledge related to this good topic is supreme! Thence scholars not have to accomplish the dissertation writing or essay thesis by their own efforts, they should get your support.
            2010-07-09 00:51 | dissertation writing service

            # re: 64位開發中去除64位平臺的內存錯誤方法  回復  更多評論   

            Students have to remember that the perfect essay writing service can help to have good grades, accomplishing the great quality sample essay. So, it's your own choice to buy custom essays or to spend hours for writing!
            2010-07-15 06:29 | custom term paper

            # re: 64位開發中去除64位平臺的內存錯誤方法  回復  更多評論   

            There is no automatic ways of research papers. Professional writers who are employed at the writing services work very hard to write the best papers!
            2011-09-30 04:18 | essay service

            # re: 64位開發中去除64位平臺的內存錯誤方法  回復  更多評論   

            Do you have papers completing difficulties? Doubt no more and buy essays, just because it's the best way out.
            2011-10-23 02:27 | essay writing
            精品无码久久久久久国产| 亚洲v国产v天堂a无码久久| 久久久久99精品成人片直播| 少妇高潮惨叫久久久久久 | 香蕉久久夜色精品升级完成| 久久夜色精品国产欧美乱| 99久久精品国产毛片| 久久精品中文字幕一区| 99久久婷婷免费国产综合精品| 久久精品国产精品亚洲人人| 久久人妻AV中文字幕| 久久99精品国产99久久| 99久久综合国产精品免费| 久久91综合国产91久久精品| 亚洲国产成人精品久久久国产成人一区二区三区综 | 久久精品免费大片国产大片| 亚洲AV日韩精品久久久久久久| 丰满少妇人妻久久久久久4| 婷婷久久久亚洲欧洲日产国码AV| 久久一区二区三区99| 99久久免费国产特黄| 色婷婷综合久久久中文字幕| 久久人人爽人爽人人爽av| 天堂久久天堂AV色综合| 伊人久久一区二区三区无码| 久久精品成人| 精品久久久久一区二区三区| 久久w5ww成w人免费| 久久天堂AV综合合色蜜桃网| 欧美久久亚洲精品| 欧美日韩中文字幕久久久不卡| 亚洲国产精品婷婷久久| 久久精品一区二区国产| AV狠狠色丁香婷婷综合久久| 日日躁夜夜躁狠狠久久AV| 亚洲午夜久久久久妓女影院| 久久久久久久久久久久久久| 日韩人妻无码一区二区三区久久99 | 婷婷久久综合九色综合绿巨人| 久久久久亚洲AV无码专区网站 | 色综合久久久久久久久五月|