Presentation is loading. Please wait.

Presentation is loading. Please wait.

編譯環境介紹.

Similar presentations


Presentation on theme: "編譯環境介紹."— Presentation transcript:

1 編譯環境介紹

2 最常用的文書編輯器vi及vim

3 安裝vim vi和vim的最大不同在於vim支 援「多顏色」的編輯環境,因 此我們選用vim
vi幾乎是所有Linux都提供的編 輯器,請同學自學 第一次執行vim系統會說沒有 這個軟體,請依照螢幕只是輸 入 sudo apt-get install vim

4 使用圖形化介面安裝vim Ubuntu內建Ubuntu software center,可以使用圖形化介面 安裝程式
標準的vim是純文字介面, Ubuntu software center允許我 們安裝圖形化介面的vim 你們喜歡圖形化介面或純文字 介面呢?

5 先使用容易上手的「圖形化」vim 輸入「a」這個字母代表我們 要開始編譯 輸入程式碼 將檔案存成~/sp/hello.c
儲存的方式是按下「ESC」然後 打w hello.c 這時候你可以看到你的程式碼的 關鍵字變色了

6 一些設定 選擇下列選項,讓vim協助我 們程式碼的排版,並列出行號 Toggle Line Numbering
Toggle auto-indent Toggle C-indenting

7 使用vim的「快捷鍵」

8 為何要學習「快捷鍵」 學會快捷鍵以後,編輯程式碼的速度可以變得更快 如果你使用的vim沒有圖形化介面,那麼你只能使用「快捷鍵」

9 Vim的編輯模式 編輯模式 按下i,o,a進入編輯模式,ESC退回一般模式 一般模式 指令模式 按下「:」進入命令列模式,ESC退回一般模式

10 vim一般模式常用功能 瀏覽 搜尋 上下左右鍵,移動游標 ctr-f, ctr-b,向下或向上移動一頁
0或「home」移到該列的第一個字元,$或「end」移到該列最後一個字 元 G移到最後一列,gg移到第一列 搜尋 「/word」向下尋找word這個字 「?word」向上尋找word這個字 n繼續尋找

11 vim一般模式常用功能 刪除、複製、貼上 x, X:小x向後刪除一個字元,大X向前刪除一個字元 dd:刪除整個列
ndd:n是一個數字,例如20,20dd代表向下刪除20列 yy:複製游標所在的那一行 nyy:複製游標所在的底下n行 p:將複製的資料,於游標的下一行開始貼上 u:復原前一個動作 [ctr]+r:重做上一個動作

12 一般指令模式 i:從目前游標所在位置開始插入(輸入) 「ESC」:退出一般模式

13 指令模式 :w,寫入檔案 :w!,強制寫入檔案 :q,離開vim :q!,強制離開vim :wq,寫入檔案並離開

14 寫程式碼常用指令 Ctr-n:自動補上該字

15 使用圖形化編輯器

16 選擇哪一個圖形化編輯器呢 - Geany

17 安裝

18 Geany的對程式碼編輯的支援 自動完成功能 參數提示功能

19 Geany的編譯環境

20 gcc 與 gdb

21 gcc常用的編譯參數 gcc xxx.c gcc xxx.c -o exec gcc xxx.c -O3 gcc xxx.c –ansi
xxx.c必需內含main function,編譯以後產生的執行檔檔名為a.out gcc xxx.c -o exec xxx.c必需內含main function,編譯以後產生的執行檔檔名為exec gcc xxx.c -O3 xxx.c必需內含main function,啟動最佳化,O後面可以為1, 2, 3 gcc xxx.c –ansi xxx.c必須使用標準的ANSI C撰寫,所有gcc的擴充語法都不可以使用 gcc xxx.c –g 產生的執行檔案可以用gdb除錯 gcc xxx.c -pg 產生的執行檔案可以用gprofile量測效能

22 一個簡單但錯誤的例子 #include <stdio.h> #include <stdlib.h> int main () { int *p; /*指標未給初始值*/ int ret; ret = scanf("%d", p); printf("ret = %d, %d", ret, *p); }

23 編譯並除錯 $gcc pointer.c –g –o pointer $gdb ./pointer gdb ./pointer /*一堆版權宣告訊息*/ (gdb)b main /*在main函數設定break point*/ Breakpoint 1 at 0x4005a5: file pointer.c, line 6. (gdb)r /*開始執行*/ Starting program: /home/shiwulo/sp/pointer Breakpoint 1, main () at pointer.c:6 6 scanf(“%d”, p); /*程式碼停在main函數的第一行*/ 請注意,紅色字體為提醒文字,並非Linux所輸出的文字

24 編譯並除錯 (gdb)n 1 /*你的執行檔pointer等著你輸入一個字*/ Program received signal SIGSEGV, Segmentation fault. 0x00007ffff7a6c742 in _IO_vfscanf_internal (s=<optimized out>, format=<optimized out>, at vfscanf.c: vfscanf.c: No such file or directory. /*gdb告訴你發生segmentation fault*/

25 編譯並除錯 (gdb)bt #0 0x00007ffff7a6c742 in…at vfscanf.c:1857 #1 0x00007ffff7a72ed9 in … at isoc99_scanf.c:37 #2 0x bb in main () at pointer.c:6 /*bt可以看到目前的呼叫堆疊*/ /*從上述的訊息可以知道pointer.c的第6行呼叫isoc99_scanf.c,isoc99_scanf.c呼叫vfscanf.c,並且在vfsacnf.c的1857行發生錯誤,由於我們相信libC應該不會有bug,所以bug很有可能發生在pointer.c的第6行*/ 請注意…代表我刪除了一些沒用的訊息

26 編譯並除錯 vfscanf 目前在此函數 Isoc99_scanf (gdb) up #1 0x00007ffff7a72ed9 … at isoc99_scanf.c:37 37 isoc99_scanf.c: No such file or directory. #2 0x bb in main () at pointer.c:6 6 scanf(“%d", p); (gdb) /*注意,還未執行up前,gdb在「呼叫堆疊」裡面是位於vfscanf,因此必須執行二次的up才會到pointer.c*/ (gdb) print p /*print可以印出某個變數的值*/ $1 = (int *) 0x0 /*到這裡我們可以確定這個程式碼是因為指標未給初始值造成錯誤*/ pointer 二次up後到此函數

27 編譯並除錯 常用的gdb功能 help 印出gdb的功能與解釋 commends定義簡短指令 b 設定breakpoint
watch觀察某一個變數是否被修改 bt 看目前的呼叫堆疊 l 看目前的程式碼 s 單步執行(遇到函數會跳進去 追蹤) n 單步執行(遇到函數不會跳進 去追蹤) p 印出某個變數的值 r 開始執行 info 會印出許多有用的東西

28 gdb -tui ./pointer ┌──pointer.c────────────────────────────────────────────────────────────────┐ │4 int main () { │ │5 int *p; /*M-f~L~GM-fM-(~YM-f~\M-*M-gM-5M-&M-e~H~]M-│ │6 int ret; │ │7 ret = scanf("%d", p); │ │8 printf("ret = %d, %d", ret, *p); │ │9 } │ │10 │ │11 │ │12 │ │13 │ │14 │ │15 │ │16 │ └───────────────────────────────────────────────────────────────────────────┘ exec No process In: L?? PC: ?? For bug reporting instructions, please see: < Find the GDB manual and other documentation resources online at: < For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from ./pointer...done. (gdb)

29 Code::Blocks(自己試試看,感覺不穩定)

30 Visual Studio Code https://code.visualstudio.com/download
vscode.cpptools

31 File->Open Folder

32 Debug(在此步驟之前,記得先編譯)

33 Debug

34 設定(文字檔案,設定完記得儲存)

35 設定中斷點

36 開始執行

37 也是一個不錯的編輯器 (有自動填入功能)

38 Visual Studio Code未提供的功能

39 小結 必須熟悉gcc及gdb,因為Linux上的工具並無法完全替代掉這二 者 一定要熟悉vi及vim
UNIX上一定會有vi UNIX與Windows不同,所有的設定檔都是「純文字」檔案,當系統崩潰 時你可以使用「single user mode」啟動,然後編輯設定檔案進行修復 可以選擇一個你最喜歡的GUI的環境,當平常寫程式用的工具

40 make:簡化常用的編譯指令

41 語法 target: source1.o source2.o… /*如果source1.o, source2.o其中有*/ gcc source1.o source2.o –o target /*一個比target還要新*/ /*就會執行gcc*/ clean: /*無預設條件*/ rm *.o

42 實例 pointer: pointer.c /*只有當pointer.c的時間比pointer還新時*/ gcc pointer.c -O3 -o pointer /*才會執行gcc指令*/ hello: hello.c gcc hello.c -O3 -o hello table: table.c gcc table.c -O3 -o table clean: /*只要執行clean就一定會執行remove*/ rm pointer rm hello rm table

43 更複雜一點點的例子 all: pointer hello table /*打make all時,只要xxx.c有任何變動,其*/ touch all /*對應的gcc會重新編譯該檔案*/ pointer: pointer.c gcc pointer.c -O3 -o pointer hello: hello.c gcc hello.c -O3 -o hello table: table.c gcc table.c -O3 -o table clean: rm pointer rm hello rm table

44 更複雜一點點的例子 all: pointer hello table /*打make all時,只要xxx.c有任何變動,其*/ touch all /*對應的gcc會重新編譯該檔案*/ pointer: pointer.c touch pointer /* hello: hello.c touch hello table: table.c touch table clean: rm pointer rm hello rm table

45 GNU C內建的效能衡量工具 gprofile

46 範例程式 如右圖,一個表格(table), 分別計算欄(col)的總和及列 (row)的總和 程式碼的程式碼如下頁所示

47 程式碼 將table初始化 列印結果 以row major方式計算 主函數,呼叫各個子函數 以col major方式計算
#define size long table[size][size]; long col[size]; long row[size]; void initTable() { int i, j; for (i=0; i< size; i++) for (j=0; j<size; j++) table[i][j]=random(); } void sumCol() { for (i=0; i<size; i++) col[j] = table[i][j]; void sumRow() { row[i] = table[i][j]; void printResult() { int i; printf(" RAW\tCol\n"); printf("%8ld\t%8ld\n", row[i], col[i]); int main() { printf("hello\n"); initTable(); sumRow(); sumCol(); printResult(); return 0; 將table初始化 列印結果 以row major方式計算 主函數,呼叫各個子函數 以col major方式計算

48 編譯的命令,及gprof命令 gcc table.c -pg -o table /*編譯,注意,要加入-pg*/ ./table /*執行,會自動產生gmon.out*/ gprof -b table gmon.out /*產生報表,如下頁所示*/

49 gprof產生的報表 主要產生 各個函數的執行時間 call graph(呼叫圖)

50 執行時間 sumCol的執行時間是42.71% sumRow的執行時間是28.48%
雖然前述二者做的加法次數一 樣。由這裡可以看出row major 會比較快! 較快的原因可以用perf觀察 initTable花了29.66%的時間

51 呼叫圖 由左圖可以看到main分別呼叫 了四個函數。 也可以觀察到呼叫這四個函數 佔了總體多少時間

52 可是人家覺得不漂亮, 人家看不懂啦

53 valgrind gcc -g table.c valgrind --tool=callgrind ./a.out kcachegrind callgrind.out.#####

54 產生的結果 (請注意每個function消耗的時間並不是很精準)

55 initTable居然佔了最多時間 (gprof的結果是sumCol)

56 小結 gprof的結果比較正確 使用valgrind可以獲得比較多的東西,但結果(特別是時間)是 不正確的
Valgrind是虛擬機器,類似java,產生一種容易profiling的中間碼,之後 再做統計 因此Valgrind並不是真的執行x86程式碼,時間上就不是那樣準確了

57 作業 使用Linux環境撰寫一個程式,這個程式必須算出「費伯納西數列」, 到第1,000,000個「費伯納西數」 費伯納西數列 繳交程式
所有.c、.h、makefile,執行檔名稱「fib」,助教執行make後必須產生fib 選出程式碼寫最好、註解最完整的三名同學,額外加5分,並公佈這三位同下 的程式碼


Download ppt "編譯環境介紹."

Similar presentations


Ads by Google