1. 程式人生 > >Biu一Biu--GDB

Biu一Biu--GDB

gcc常見編譯選項

  • ** -c **:只啟用預處理、編譯和彙編,也就是生成obj檔案
  • ** -S **:只啟用處理和編譯,把檔案編譯成彙編程式碼
  • ** -o **:定製目標名稱,預設的時候編譯出來的可執行程式名為a.exe(windows)或a.out(linux)
  • ** -Wall **:開啟一些很有用的編譯警告
  • ** -std **:指定C標準,如-std=99,使用C99標準
  • ** -g **:指示編譯器,編譯的時候新增除錯資訊
  • ** -O0 -O1 -O2 -O3 **:編譯器的優化選項的4個級別,-O0表示沒有優化,-O1為預設值,-O3優化級別最高

/*
file_name: swap.c
*/ 

#include<stdio.h>
void swap(int a, int b)
{
    int t;
    t = a;
    a = b;
    b = t;
}

int main()
{
    int a=3, b=4;
    swap(a,b);
    printf("%d %d",a,b);
    return 0;   
}

GDB的使用

什麼是GDBhttps://www.bing.com/knows/search?q=gdb&mkt=zh-cn&FORM=BKACAI
http://www.gnu.org/software/gdb/

一般來說,GDB主要幫助你完成以下四個方面的內容
1、啟動你的程式,可以按照你的自定義的要求隨心所欲的執行程式
2、可以讓被除錯的程式在你所指定的調置的斷點處停住。(斷點可以是條件表示式)
3、當程式被停住時,可以檢查此時你的程式中所發生的事
4、你可以改變你的程式,將一個BUG產生的影響修正,從而測試其他BUG

GDB常見命令

簡稱 全稱 備註
l list 顯示指定行號或者指定函式附近的原始碼
b break 在指定行號或指定函式開頭設定斷點
r run 執行程式,直到程式結束或遇到斷點
c continue 在程式中斷後繼續執行程式,直到程式結束或遇到斷點停下。注意在程式開始執行前只能用r,而不能用c
n next 執行一條語句。如果有函式呼叫,則把它當做一個整體
s step 執行一條語句。如果有函式呼叫,則進入函式內部
u until 執行到指定行號或指定函式的開頭
p print 顯示變數或表示式的值
disp display 把一個表示式設定為display,當程式每次停下來時都會顯示其值
cl clear 取消斷點,和b格式相同,如果該位置有多個斷點,將同時取消
i info 顯示各種資訊,如i b顯示所有斷點,i disp顯示display,而i lo顯示所有區域性變數
bt backtrace 列印所有棧幀資訊

呼叫棧(Call Stack)

呼叫棧描述的是函式之間的呼叫關係。呼叫棧由棧幀(Stack Frame)組成,每個棧幀對應著一個未執行完的函式。在GDB中可以用backtrace(簡稱bt)命令列印所有棧幀資訊。若要用p命令列印一個非當前棧幀的區域性變數,可以用frame命令選擇另一個棧幀

拿個程式來玩玩,swap.c檔案

#include<stdio.h>
void swap(int a, int b){
    int t;t = a;a = b;b = t;
}

int main(){
    int a=3, b=4;
    swap(a,b);
    printf("%d %d",a,b);
    return 0;   
}

*** 程式的目的是交換a和b的值,然而並沒有交換交換成功 ***

原因:

  • 函式的形參和在函式內部宣告的變數都是該函式的區域性變數。無法訪問其他函式的區域性變數。
  • 區域性變數的儲存空間是臨時分配的,函式執行完畢時,區域性變數的空間將被釋放,其中的值無法保留到下次使用。
  • 如果要實現真正的交換,我們應該傳入的是儲存變數的地址,此時函式swap的形參型別應該為指標型別

PS:
C語言的變數都是放在記憶體中的,而記憶體中間的每一個位元組都有一個稱為地址(address)的編號。
每一個變數都佔有一定數目的位元組(可以用sizeof運算子獲得),其中第一個位元組的地址稱為變數的地址。

o(*≧▽≦)ツ┏━┓拿個遞迴程式來玩玩

#include<stdio.h>
int f(int n)
{
    return n == 0 ? 1 : f(n-1)*n;
}
int main()
{
    printf("%d\n",f(3));
    return 0;
}

在C語言的函式中,呼叫自己和呼叫其他函式沒有任何本質區別,都是建立新棧幀,傳遞引數並修改當前程式碼行。在函式執行體完畢後刪除棧幀,處理返回值,並修改當前程式碼行數。

以上呼叫棧的一個比喻

皇帝(擁有main函式的棧幀):大臣,你給我算下f(3)
大臣(擁有f(3)的棧幀):知府,你給我算下f(2)
知府(擁有f(2)的棧幀):縣令,你給我算下f(1)
縣令(擁有f(1)的棧幀):師爺,你給我算下f(0)
師爺(擁有f(0)的棧幀):回老爺,f(0)=1
縣令(心算f(1)=f(0)1=1):回知府大人,f(1)=1
知府(心算f(2)=f(1)
2=2):回大人,f(2)=2
大臣(心算f(3)=f(2)*3=6):回皇上,f(3)=6
皇上滿意了

emmmmmm。。。。。。。。。。。。

最後歡迎來我的個人部落格看看https://shansan.top