? ? ?本篇博客詳細分析,Linux平臺上C程序的編譯過程與調試方法,這也是我們后續程序開發的基礎。
目錄
一、第一個hello world程序
1.1 創建.c文件
1.2 編譯鏈接? +? 運行可執行程序
二、編譯鏈接過程
2.1?預編譯階段
2.2?編譯階段
2.3?匯編階段
2.4?鏈接階段
三、gcc 分步編譯鏈接
?3.1 一步完成編譯鏈接生成可執行程序
3.2 分兩步完成編譯鏈接生成可執行程序
3.3 多文件編譯鏈接
四、 make工具和makefile文件
4.1 什么是make和makefile
4.2 利用make工具完成上一小節的自動化編譯過程
4.2.1 編寫makefile文件
4.2.2 利用make工具自動生成可執行程序
4.2.3 總結
五、gdb 調試
5.1?Debug 版本和 Release 版本
5.2?單進程、單線程基礎調試命令
5.3 使用GDB軟件調試程序的基本步驟
5.4 如何在自動化編譯工具中加入命令,自動生成含有調試信息的Debug版本
5.5?多進程調試命令
5.6?多線程調試命令
一、第一個hello world程序
1.1 創建.c文件
1.2 編譯鏈接? +? 運行可執行程序
? ? ? C語言是一門編譯型語言,編譯型語言首先將源代碼編譯生成機器語言,再由機器運行機器碼(二進制)。對于編譯型語言,繞不過的就是編譯器。GCC(GNU編譯器套件):GNU Compiler Collection。可以編譯C、C++、JAVA、Fortran、Pascal、Object-C、Ada等語言。
gcc是GCC中的GNU C Compiler(C 編譯器),g++是GCC中的GNU C++ Compiler(C++編譯器)
? ? ?注意:對于Linux平臺下,生成的可執行程序沒有后綴.exe ,關于編譯鏈接的過程,我們下面作詳細分析。
二、編譯鏈接過程
2.1?預編譯階段
a) 刪除所有的“#define”,并且展開所有的宏定義;
b) 處理所有的條件預編譯指令,“#if”、“#ifdef”、“#endif”等;
c) 處理“#include”預編譯指令,將被包含的文件插入到該預編譯指令的位置;
d) 刪除所有的注釋;
e) 添加行號和文件名標識,以便于編譯器產生調試用的符號信息及編譯時產生編譯錯誤和警告時顯示行號;
f) 保留所有的#pragma 編譯器指令,因為編譯器需要使用它們。
2.2?編譯階段
詞法分析、語法分析、語義分析,代碼優化,匯總符號。
2.3?匯編階段
將匯編指令翻譯成二進制格式,生成各個 section,生成符號表。
2.4?鏈接階段
a) 合并各個 section,調整 section 的起始位移和段大小,合并符號表,進行符號解析, 給符號分配虛擬地址
b) 符號重定位
三、gcc 分步編譯鏈接
3.1 一步完成編譯鏈接生成可執行程序
gcc? -o main main.c
3.2 分兩步完成編譯鏈接生成可執行程序
step1、gcc? ?-c? ?main.c? ?? ? ? ? ? ? ? ? 生成main.o文件
step2、gcc? ?-o? ?main? ? ?main.o? ? ?生成main(main.exe)可執行程序
3.3 多文件編譯鏈接
? ? 創建3個源文件如下:add.c? max.c? main.c?
方式1:一步直接完成編譯鏈接生成可執行程序
方式2:分兩步;
- 首先,先把每個文件生成對應的.o文件, gcc -c xxx.c
- 其次,將所有的.o文件鏈接生成可執行程序文件main, gcc -o main? main.o xx.o xx.o
四、 make工具和makefile文件
4.1 什么是make和makefile
?????? 當源碼文件比較多的時候就不適合通過直接輸入gcc命令來編譯,這時候就需要一個自動化的編譯工具, 這就是make工具,make是一條命令,makefile是一個文件,兩個搭配使用,完成項目自動化構建。
- make:一般說GNU Make,是一個軟件,用于將源代碼文件編譯為可執行的二進制文件,make工具主要用于完成自動化編譯。make工具編譯的時候需要Makefile文件提供編譯文件。
- Makefile:make工具所使用的文件,Makefile指明了編譯規則。makefile帶來的好處就是“自動化編譯”,一旦寫好,只需要一個make命令,整個工程完全自動編譯,極大的提高了軟件開發的效率。
4.2 利用make工具完成上一小節的自動化編譯過程
4.2.1 編寫makefile文件
工程是需要被清理的,像clean這種,沒有被第一個目標文件直接或間接關聯,那么它后面所定義的命令將不會被自動執行, 不過,我們可以顯示要make執行。即命令——“make clean”,以此來清除所有的目標文件,以便重編譯。?
4.2.2 利用make工具自動生成可執行程序
4.2.3 總結
? ? ? 利用make工具完成自動化編譯的大致步驟如下:
- 提供好所有的源文件.c和makefile文件
- 執行命令make, 自動生成編譯鏈接四個階段的所有文件?
- 清理中間的目標文件,執行命令:make? clean
五、gdb 調試
5.1?Debug 版本和 Release 版本
1、Debug 版本
? ? ?Debug 版本為可調試版本,生成的可執行文件中包含調試需要的信息。我們作為開發人 員,最常用的就是 debug 版本的可執行文件。 Debug 版本的生成: 因為調試信息是在編譯過程時加入到中間文件(.o)中的,所以必須在編譯時控制其生成包含調試信息的中間文件。如:gcc -o hello hello.c -g
2、Release 版本
? ? ? ? Release 版本為發行版本,是提供給用戶使用的版本。用 gcc 默認生成的就是 Release 版 本。 因此,我們使用gdb進行調試 ,首先將源代碼編譯、鏈接生成 Debug 版本的可執行文件,然后通過‘gdb Debug 版本 的可執行文件名’進入調試模式。
5.2?單進程、單線程基礎調試命令
命令 | 作用 |
l | 顯示代碼,默認一次只顯示10行 |
b+行號 | 給指定行添加斷點 |
b+函數名 | 給指點函數的第一有效行添加一個斷點 |
info break | 顯示斷點信息 |
delete +斷點編號 | 刪除指定斷點 |
r(run) | 運行程序,啟動調試代碼 |
n(next) | 單步執行 |
c (continue) | 繼續執行,直接執行到下一個斷點處 |
s(step) | 進入將要被調用的函數中執行 |
?finish | 跳出函數 |
p +變量 (print) | 打印變量的值 |
p + &變量 | 打印變量的地址 |
p arr(數組名) | 打印數組所有元素的值 |
ptype? + 變量 | 顯示變量類型 |
bt(breaktrace) | 顯示函數調用棧 |
q (quit) | 退出調試 |
- l +行號 就能跳轉到該行。
- l +文件名:行號 能跳轉文件 跳轉別的文件的第幾行 l add.c :1;
- 顯示函數調用的棧關系 上邊信息顯示當前所在位置,下面信息顯示執行完當前程序會回到哪一行。 ?
5.3 使用GDB軟件調試程序的基本步驟
? ? ? ?GDB是GNU開源組織發布的一個強大的UNIX下的程序調試工具。或許,各位比較喜歡那種圖形界面方式的,像VC、BCB等 IDE的調試,但如果你是在UNIX平臺下做軟件,你會發現GDB這個調試工具有比VC、BCB的圖形化調試器更強大的功能。調試程序的基本步驟如下:
- 生成包含調試信息的Debug版本,如:gcc? -o test test.c -g
- 執行命令:gdb? test
- 進入調試,利用常用的命令
5.4 如何在自動化編譯工具中加入命令,自動生成含有調試信息的Debug版本
在前面定義一個 GDB=-g,在生成規則后加$(GDB),就會取GDB的值;不讓生成debug版本就是把GDB置空(GDB=)。 ?
5.5?多進程調試命令
(gdb)set follow-fork-mode mode
mode 可以選擇 parent 或者 child,即:選擇調試那個進程。 注意:未被跟蹤調試的進程會直接執行結束。
5.6?多線程調試命令
a) 利用 info threads 查看線程信息;
b) thread id 調試目標 id 指定的線程;
c) set scheduler-locking off | on | step; “off”表示不鎖定任何線程; “on”只有當前被調試的線程繼續運行; “step”在單步執行的時候,只有當前線程會執行;
? ? ? 以上就是全部內容!請務必掌握,這是后續學習的基礎,歡迎大家點贊加關注評論,您的支持是我前進最大的動力!下期再見!?