1.什么是bug?
bug:程序漏洞,也就是程序中存在的問題。
2.什么是調試?
當我們發現了程序中的問題后就會解決問題,前提是要找到問題,那么進行調試(debug)以此來找到問題。
3.debug 和 release
在vs里編寫代碼時就有 debug 和 release 兩個選項:
Debug 通常稱為調試版本,包含調試信息,但是不會對代碼進行優化,可以進行調試的。
Release 稱為發布版本,是會對代碼自動進行代碼優化的,不可以調試,當程序員寫好程序后并對程序進行測試,測試完成后就會發布release版本,面向用戶使用。沒有包含調試信息,所以是不可以進行調試的。
從上面我們就可以知道 debug 版本要比 release 版本要大得多,就是因為debug里面包含調試信息
4.vs調試技巧的快捷鍵
4.1準備環境
環境就是 vs 的 debug 版本
4.2調試常用的快捷鍵
F9:創建斷點和取消斷點
斷點的作用是可以在程序的任意位置設置斷點,打上斷點就可以使得程序執行到想要的位置暫停執行,之后我們就可以使用 F10、F11 更加深層次的觀察代碼的執行細節
條件斷點:滿足這個條件,才觸發斷點
在下面輸入條件:
F5:啟動調試,經常用來直接跳到下一個斷點處,一般是和F9配合使用。
F10:逐過程,通常用來處理一個過程,一個過程可以是一次函數調用,也可以是一條語句。
F11:逐語句,就是每次都執行一條語句,但是這個快捷鍵可以使我們進入函數內部,更加仔細地觀察語句,此時就必須使用 F11,如果使用 F10 ,直接完成函數調用。
CTRL+F5:開始執行不調試。
5.監視和內存觀察
5.1監視
當我們想明白每一個變量變化的每一個過程的時候,我們就可以選擇監視,但是監視的前提是一定要調試才可以監視到每一個變量的變化。
?上面的監視窗口任意選一個就行,然后按 F10 就可以觀察到了:
上面經歷五次循環之后的數組內容
5.2 內存
如果想看數組arr、變量num、變量a的地址可以在地址欄那里寫入:arr(數組名本來就是地址)? &num? &a
6.調試舉例1
求 1!+2!+3!+4!+...10! 的和,我這里的代碼寫的是 3 是為了方便檢查寫的代碼是否正確:
(你們運行的時候可以改動一下)
int main()
{int n = 3;int i = 0;int sum = 0;for (n = 1; n <= 3; n++){int ret = 1;for (i = 1; i <= n; i++) {ret = ret * i;}sum +=ret;}printf("%d\n", sum);return 0;
}
7.調試舉例2
在VS2022、X86、Debug 的環境下,編譯器不做任何優化的話,下?代碼執?的結果是啥?
#include <stdio.h>
int main()
{int i = 0;int arr[10] = {1,2,3,4,5,6,7,8,9,10};for(i=0; i<=12; i++){arr[i] = 0;printf("hehe\n");}return 0;
}
當我們在上面要求的環境中運行時就會發現:
這個時候就要調試看看到底怎么回事?
其實調試到這里我們就可以發現這里是i的地址,當我們再按一次F10時,i 明明該為13了,但是 i 就被初始化為0了,所以才會進入死循環。
本質原因:
棧區內存中習慣是從高地址開始使用,因為先創建的是變量 i 的地址,所以 i 的地址比數組 arr 的地址高,而又因為數組在內存當中的存放是下標越大的,地址越高,也就是從低地址開始使用的,本來數組就越界了,所以有可能數組就會覆蓋到 i ,所以進入死循環。而 i 和 arr剛好間隔兩個整形的空間,這完全取決于環境,每次的變量在內存的分配都是由編譯器指定的,所以演示這道題時規定了環境。
如果將 i 和 arr 初始化的順序交換一下,就不會出現這種情況了
或者是改成 release 環境下,也不會出現死循環,這是因為 release 會自動地優化代碼,但是會報錯,因為數組越界了
8.變成常見的錯誤
8.1 編譯型錯誤:
檢查語法的錯誤——最簡單的
8.2鏈接型錯誤:
聲明自己寫的同文件沒有寫對呀,等等~
8.3運行時錯誤
前面的兩步都沒有報錯,但是運行的結果和自己預期的結果不一樣,這個是最麻煩的,這個時候就要進行調試了