C畢業(yè)設(shè)計外文翻譯
《C畢業(yè)設(shè)計外文翻譯》由會員分享,可在線閱讀,更多相關(guān)《C畢業(yè)設(shè)計外文翻譯(7頁珍藏版)》請在裝配圖網(wǎng)上搜索。
1、Fixing Memory Problems This chapter is about finding bugs in C/C++ programs with the help of a memory debugger. A memory debugger is a runtime tool designed to trace and detect bugs in C/C++ memory management and access. It does not replace a general debugger. In the following sections, we will
2、describe the memory access bugs that typically occur in C/C++ programs, introduce memory debuggers, and show with two examples how these tools find bugs. We will then show how to run memory and source code debuggers together, how to deal with unwanted error messages by writing a suppression file
3、, and what restrictions need to be considered. 4.1 Memory Management in C/C++ – Powerful but Dangerous The C/C++ language is able to manage memory resources, and can access memory directly through pointers. Efficient memory handling and “programming close to the hardware” are reasons why C/C++ r
4、eplaced assembly language in the implementation of large software projects such as operating systems, where performance and low overhead play a major role. The allocation of dynamic memory (also known as heap memory) in C/C++ is under the control of the programmer. New memory is allocated with f
5、unctions such as malloc() and various forms of the operator new. Unused memory is returned with free() or delete. The memory handling in C/C++ gives a large degree of freedom, control, and performance, but comes at a high price: the memory access is a frequent source of bugs. The most frequent s
6、ources of memory access bugs are memory leaks, incorrect use of memory management, buffer overruns, and reading uninitialized memory. 33 34 4 Fixing Memory Problems 4.1.1 Memory Leaks Memory leaks are data structures that are allocated at runtime, but not deallocated once they are no longer ne
7、eded in the program. If the leaks are frequent or large, eventually all available main memory in your computer will be consumed. The program will first slow down, as the computer starts swapping pages to virtual memory, and then fail with an out-of-memory error. Finding leaks with a general debug
8、ger is difficult because there is no obvious faulty statement. The bug is that a statement is missing or not called. 4.1.2 Incorrect Use of Memory Management A whole class of bugs is associated with incorrect calls to memory management: freeing a block of memory more than once, accessing memory
9、 after freeing it, or freeing a block that was never allocated. Also belonging to this class is using delete instead of delete[] for C++ array deallocation, as well as using malloc() together with delete, and using new together with free(). 4.1.3 Buffer Overruns Buffer overruns are bugs where m
10、emory outside of the allocated boundaries is overwritten, or corrupted. Buffer overruns can occur for global variables, local variables on the stack, and dynamic variables that were allocated on the heap with memory management. One nasty artifact of memory corruption is that the bug may not beco
11、me visible at the statement where the memory is overwritten. Only later, another statement in the program will access this memory location. Because the memory location has an illegal value, the program can behave incorrectly in a number of ways: the program may compute a wrong result, or, if the
12、 illegal value is in a pointer, the program will try to access protected memory and crash. If a function pointer variable is overwritten, the program will do a jump and try to execute data as program code. The key point is that there may be no strict relation between the statement causing the me
13、mory corruption and the statement triggering the visible bug. 4.1.4 Uninitialized Memory Bugs Reading uninitialized memory can occur because C/C++ allows creation of variables without an initial value. The programmer is fully responsible to initialize all global and local variables, either throu
14、gh assignment statements or through the 4.2 Memory Debuggers to the Rescue 35 various C++ constructors. The memory allocation function malloc() and operator new also do not initialize or zero out the allocated memory blocks. Uninitialized variables will contain unpredictable values. 4.2 Memory
15、Debuggers to the Rescue The above categories of memory access bugs created a need for adequate debugging tools. Finding bugs related to leaked, corrupted, or uninitialized memory with a conventional debugger such as GDB turned out to be unproductive. To deal with memory leaks in large software p
16、rojects, many programmers came up with the same idea. They created memory management functions/operators with special instrumentation to track where a memory block was allocated, and if each block was properly deallocated at the end of the program. Since everybody had the same memory bugs in the
17、ir C/C++ programs, and since everybody improvised with custom instrumentation to track down at least some of these bugs, a market for a tool called memory debugger was created. The most wellknown tool is Purify, released in 1991 by Pure Software. Purify’s name has since become synonymous with me
18、mory debugging. There is also Insure++, Valgrind, and BoundsChecker, among others. See the tools Appendix B.4 starting on page 198 for references and the survey in [Luecke06] for a comparison of features. Memory debuggers do detailed bookkeeping of all allocated/deallocated dynamic memory. They
19、also intercept and check access to dynamic memory. Some memory debuggers can check access to local variables on the stack and statically allocated memory. Purify and BoundsChecker do this by object code instrumentation at program link time, Insure++ uses source code instrumentation, and Valgrind
20、executes the program on a virtual machine and monitors all memory transactions. The code instrumentation allows the tools to pinpoint the source code statement where a memory bug occurred. The following bugs are detectable by a memory debugger: ? Memory leaks ? Accessing memory that was alread
21、y freed ? Freeing the same memory location more than once ? Freeing memory that was never allocated ? Mixing C malloc()/free()with C++ new/delete ? Using delete instead of delete[] for arrays ? Array out-of-bound errors ? Accessing memory that was never allocated ? Uninitialized memory read
22、? Null pointer read or write We will show in the next section how to attach a memory debugger to your program, and how the tool finds and reports bugs. 36 4 Fixing Memory Problems 4.3 Example 1: Detecting Memory Access Errors Our first example is a program that allocates an array in dynamic mem
23、ory, accesses an element outside the final array element, reads an uninitialized array element, and finally forgets to deallocate the array. We use the public domain tool Valgrind on Linux as the memory debugger, and demonstrate how the tool automatically detects these bugs. This is the code of
24、our program main1.c:
1 /* main1.c */
2 #include
25、(n=0;n
26、heck=yes ./a.out In the following sections we go through the error list reported by Valgrind. 4.3.1 Detecting an Invalid Write Access The first – and perhaps most severe – error is a buffer overrun: the accidental write access to array element A[100]. Because the array has only 100 elements, the
27、 highest valid index is 99. A[100] points to unallocated memory that is located just after the memory allocated for array A. Valgrind thus reports an “invalid write” error: ==11323== Invalid write of size 4 ==11323== at 0x8048518: main (main1.c:9) ==11323== Address 0x1BB261B8 is 0 bytes after
28、a block ==11323== of size 400 alloc’d ==11323== at 0x1B903F40: malloc ==11323== (in /usr/lib/valgrind/vgpreload_memcheck.so) ==11323== by 0x80484F2: main (main1.c:6) The string "==11323==" refers to the process ID and is useful when Valgrind is checking multiple processes 1. The important piec
29、e of information is that an invalid 1 Valgrind will, per default, check only the first (parent) process that has been invoked. Use option --trace-children=yes to check all child processes as well. 4.3 Example 1: Detecting Memory Access Errors 37 write occurs in line 9 of main1.c. There is also a
30、dditional information revealing the address of the closest allocated memory block and how it was allocated. The memory debugger guesses that the invalid write in line 9 is related to this memory block. The guess is correct because both belong to the same array A. Note that Valgrind is able to ca
31、tch an out-of-array-bounds errors only when the array is allocated as dynamic memory with malloc() or new. This is the case in the example with the statement in line 6: 6 int* A = (int*)malloc( sizeof(int)*size ); If the example were instead written as int A[size] in line 6, then A would be a l
32、ocal variable located on the stack and not on the heap. It turns out that Valgrind does not detect such an error but Purify is able to catch it. This shows that not all memory debuggers will report exactly the same errors. 修正內(nèi)存問題 本章是關(guān)于利用內(nèi)存BUG調(diào)試器的幫助,來發(fā)現(xiàn)C或C++程序中的BUG。內(nèi)存調(diào)試器是在C或C++程序管理或存儲
33、時用于追蹤和發(fā)現(xiàn)BUG的運行時工具。它不能取代一個正規(guī)的調(diào)試器。在一下的章節(jié),我們將描述幾個代表性的在C或C++程序中處理的內(nèi)容BUG,介紹內(nèi)容調(diào)試器,并且介紹兩個內(nèi)存如何發(fā)現(xiàn)BUG的例子。我們?nèi)缓髮⒀菔救绾问箖?nèi)存與編碼調(diào)試器一起運行,怎么去處理不需要的錯誤信息通過寫文件,需要去考慮程序需要的限制。 4.1 內(nèi)存管理在C或C++中強健但是危險 C或C++語言能夠管理內(nèi)存資源,并且通過指針直接讀取內(nèi)存。高效的內(nèi)存處理和“直接控制硬件”是規(guī)劃大型例如操作系統(tǒng)的軟件工程取代匯編語言的原因,高性能和低限制是它作為一個重要角色的原因。動態(tài)內(nèi)存的分配(眾所周知的堆內(nèi)存)在C或C++中是在程序員的控制之
34、下的。新內(nèi)存被分配擔(dān)任起例如malloc()和各種有程序員構(gòu)成的新的指針。不被使用的內(nèi)存被free()或delete回收。 4.1.1 內(nèi)存泄漏 內(nèi)存泄漏是在運行時的內(nèi)存分配結(jié)構(gòu),但是它們只需要我們分配一次,我們卻分配了多次。如果內(nèi)存泄漏經(jīng)常發(fā)生或者十分巨大,最后你電腦的主要內(nèi)存將被耗盡。程序首先會變慢,然后電腦開始使用分頁技術(shù)虛擬內(nèi)存,然后以內(nèi)存溢出錯誤宣告失敗。用普遍的調(diào)試器發(fā)現(xiàn)內(nèi)存溢出錯誤是困難的因為它沒有一個明顯的錯誤聲明。BUG會丟失或不能被聲明。 4.1.2 錯誤的內(nèi)存管理用法 一套完整BUG集合與錯誤聲明對于內(nèi)存管理來說:解除一個錯誤的內(nèi)存超過一次,在解除以后訪問內(nèi)存,或
35、解除一個從分配過的阻塞內(nèi)存。用delete代替delete[]在C++數(shù)組中也屬于這個類,也可以用malloc()和delete一起使用,用new和free()一起使用。 4.1.3 緩存溢出 緩存溢出內(nèi)存被重載時超出范圍的BUG,或損壞。緩存溢出會由屬性引起,在堆中的局部變量,通過內(nèi)存管理分配在棧上的動態(tài)變量。 在內(nèi)存中令人討厭的事是內(nèi)存重載的時候BUG沒有被聲明。只有在以后,另一個在問題中的聲明將存取在內(nèi)存中。因為內(nèi)存含有一個不合法的變量,內(nèi)存會在一下幾個方面表現(xiàn)出異常:這個問題得出一個錯誤的結(jié)果,或者如果一個不合法的值在指針上,這個問題將試圖存取和保護(hù)內(nèi)存。如果在存取的過程中一個動
36、態(tài)指針可變,程序?qū)⑻幚硭凑粘绦虼a。鍵指針不是引起內(nèi)存溢出和嚴(yán)重問題的關(guān)鍵。 4.1.4 非原始內(nèi)存BUG 讀非原始內(nèi)存是因為C或C++允許創(chuàng)建變量在沒有一個原始值的情況下。程序員有完全的責(zé)任給所有的屬性和局部變量賦值,也可以通過聲明,或各種C++的構(gòu)造器。內(nèi)存引導(dǎo)功能malloc()和操作new也不能夠定義變量或者是內(nèi)存為空。未定義的變量中包含不穩(wěn)定的值。 4.2 內(nèi)存調(diào)試解決 上述問題處理BUG需要創(chuàng)建一個強大的BUG處理工具。尋找BUG與漏洞有關(guān),不完善的,只有普通BUG調(diào)試器GDB內(nèi)存變得不安全。應(yīng)付大型軟件工程中的系統(tǒng)漏洞,很多程序員都提出了相同的意見。他們建立內(nèi)存管理機制
37、為一個被分配阻塞內(nèi)存利用不同的機制,并且確保是否每個阻塞內(nèi)存在最后都得到了分配。 自從每個人在各自的C或C++程序中遇到相同的內(nèi)存BUG,自從每個人用傳統(tǒng)的內(nèi)存處理器追蹤到很少的幾個BUG,一系列叫內(nèi)存調(diào)試器的工具誕生了。最總所周知的是Purify,在1991年被Pure軟件公司發(fā)布。Purify一直被用于一些同類的內(nèi)存調(diào)試器。也有Insure++,Valgrind,也有BoundsChecker,除此之外的一些其他同類工具。 內(nèi)存調(diào)試器作用于所有被動態(tài)分配的內(nèi)存。他們同樣攔截和檢查分配過的內(nèi)存。一些內(nèi)存調(diào)試器能夠檢查一些被分配在棧上的局部變量和被分配過的內(nèi)存。Purify和BoundsC
38、hecker用代碼編譯工具完成這些工作在程序連接期間,Insure++利用源代碼編譯工具,Valgrind則把程序先執(zhí)行在虛擬機上并且監(jiān)聽所有的內(nèi)存處理。源代碼編譯工具允許一個BUG發(fā)生的時候精確的找到代碼發(fā)生的位置。 一下的BUG被內(nèi)存調(diào)試器處理: 1. 內(nèi)存泄漏 2. 訪問已經(jīng)被釋放的內(nèi)存 3. 釋放一段內(nèi)存空間不止一次 4. 釋放從未被分配過的內(nèi)存 5. 把C中的malloc(),free()與C++中的 new/delette混雜在一起 6. 在數(shù)組中用delete代替delete[] 7. 數(shù)組越界錯誤 8. 訪問從未被分配過的內(nèi)存 9. 未被定義過的內(nèi)存讀取
39、10. 空指針讀或?qū)? 我們將在下一章節(jié)演示如何為你的程序附屬內(nèi)存調(diào)試器,內(nèi)存調(diào)試器如何發(fā)現(xiàn)和報告錯誤。 4.3 例1檢測內(nèi)存訪問錯誤 我們第一個例子是在動態(tài)內(nèi)存中分配一列,存取最后一個在數(shù)組序列外的元素,讀一個未定義的數(shù)組元素,最終忘記分配這個數(shù)組。我們用公共范圍工具Valgrind在Linux上作為內(nèi)存調(diào)試器,演示內(nèi)存調(diào)試器如何自動的解決這些BUG。 4.3.1 檢查一個無用的寫操作 第一個最大最嚴(yán)重的錯誤是緩存溢出:對這個數(shù)組以外的寫操作。因為這個數(shù)組只有100個元素,最大的有效索引是99。100指針超過了這個數(shù)組的有效范圍。一次報告一個無用的寫錯誤。 ==11323== In
40、valid write of size 4 ==11323== at 0x8048518: main (main1.c:9) ==11323== Address 0x1BB261B8 is 0 bytes after a block ==11323== of size 400 alloc’d ==11323== at 0x1B903F40: malloc ==11323== (in /usr/lib/valgrind/vgpreload_memcheck.so) ==11323== by 0x80484F2: main (main1.c:6) 這個字符串,應(yīng)用一個過程ID,當(dāng)Va
41、lgrind檢查過程的時候是十分必要的。最重要的信息塊是在第9行的寫操作。這依然有信息補充說明根據(jù)以離內(nèi)存最近的區(qū)域和它是怎么被分配的。內(nèi)存調(diào)試器猜測第9行與內(nèi)存阻塞有關(guān)。這個猜測被修正因為兩個都屬于數(shù)組A。 在Valgrind中內(nèi)存中數(shù)組下標(biāo)越界錯誤只有當(dāng)動態(tài)內(nèi)存被定義為malloc()或new的情況下。這個是第6行的實例: 6 int*A = (int * )malloc (sizeof(int) * size) 如果例子中書寫A[size]在第6行,A將被定義在一個局部變量上,堆而不是棧上。它表現(xiàn)出Valgrind不能夠發(fā)現(xiàn)這樣的錯誤但是Purity可以捕獲到它們。它說明不是所有的內(nèi)存調(diào)試器都能捕獲到同一個錯誤。
- 溫馨提示:
1: 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
2: 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
3.本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
5. 裝配圖網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 6.煤礦安全生產(chǎn)科普知識競賽題含答案
- 2.煤礦爆破工技能鑒定試題含答案
- 3.爆破工培訓(xùn)考試試題含答案
- 2.煤礦安全監(jiān)察人員模擬考試題庫試卷含答案
- 3.金屬非金屬礦山安全管理人員(地下礦山)安全生產(chǎn)模擬考試題庫試卷含答案
- 4.煤礦特種作業(yè)人員井下電鉗工模擬考試題庫試卷含答案
- 1 煤礦安全生產(chǎn)及管理知識測試題庫及答案
- 2 各種煤礦安全考試試題含答案
- 1 煤礦安全檢查考試題
- 1 井下放炮員練習(xí)題含答案
- 2煤礦安全監(jiān)測工種技術(shù)比武題庫含解析
- 1 礦山應(yīng)急救援安全知識競賽試題
- 1 礦井泵工考試練習(xí)題含答案
- 2煤礦爆破工考試復(fù)習(xí)題含答案
- 1 各種煤礦安全考試試題含答案