Linux學習筆記(4)

2022-01-10 18:00:01

🍅Linux編譯器gcc與g++🍅

我們習慣用gcc 編譯C語言程式碼,g++編譯C++的程式碼

gcc也可以編譯Go語言程式之類的,gcc可以根據檔案字尾來判斷當前程式所用的語言

以test.c為例:

gcc -E test.c -o test.i 預處理:完成宏替換,去掉註釋,標頭檔案包含等工作

gcc -S test.i -o test.s 編譯: 把C語言程式碼轉化成組合語言的程式碼

gcc -c test.s -o test.o 組合:把組合語言的程式碼轉成機器語言(二進位制序列)

gcc test.o -o mytest 連結:生成可執行程式(預設是動態連結)

🍅gcc演示🍅

下面對每步進行演示

📖①**vim test.c**

在這裡插入圖片描述

📖②gcc -E test.c -o test.i

-E 作用:預處理,但不生成檔案

-o的作用:把生成的內容輸出到檔案,此外有給檔案起名的作用

gcc -E test.c -o test.i 裡的-o就是把預處理的內容輸出到test.i裡,不然直接列印到螢幕上了

cat -n test.i

test.i的內容

在這裡插入圖片描述

📖③gcc -S test.i -o test.s

-S:編譯 ,不生成檔案

-o 把生成的內容放入test.s

cat -n test.s

生成的組合程式碼如下:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-9bUigwPn-1641739327072)(../typora 圖片/image-20220109164421642.png)]

📖④gcc -c test.s -o test.o

-c 組合不生成檔案

-o 把生成的內容放入test.o

cat -n test.o

看不懂對吧,我也看不懂,可以轉為二進位制檔案看

xxd test.o

在這裡插入圖片描述

看不懂對吧 我也看不懂🐱‍🏍

📖⑤gcc test.o -o mytest

這一步寫成 gcc test.o -o mytest.exe 效果一樣,Linux不是根據擴充套件名來給檔案歸類的,反正都是可執行檔案,具有x許可權

gcc test.o :連結 生成可執行檔案.

mytest檔案就不看了,和上面的test.o差不多,也是二進位制檔案

連結分為動態連結和靜態連結,預設是動態連結

ldd和file可以判斷連結型別

📖 ldd mytest

在這裡插入圖片描述

.so可以判斷動態連結,.a判斷是靜態連結

libc.so.6就是個動態庫,libc.a就表示是個靜態庫

在這裡插入圖片描述

📖file mytest

📖 英文時間:dynamically linked==動態連結
在這裡插入圖片描述

既然有動態連結 肯定就有靜態連結 兩者區別又是什麼?

動態連結用到的是靜態庫,執行時載入庫。

靜態連結則是直接包含庫,所以靜態連結生成的檔案會很大

怎麼生成靜態連結的可執行檔案?

加-static

舉例:gcc test.c -o mytest-s -static(如果報錯了拉到下一個塊解決報錯)

生成的mytest-s就是靜態連結的,看看具體資訊

file mytest-s

在這裡插入圖片描述

📖 英文時間:statically linked==靜態連結

📖 再比較下動態和靜態庫的大小

在這裡插入圖片描述

靜態連結生成的檔案大小是動態連結生成的100倍左右

不過靜態連結也有優點,沒有那麼依賴設定環境,拿過來就能用。

不加-static預設是動態連結

🍅解決static報錯問題🍅

報錯資訊:

/usr/bin/ld: cannot find -lc
collect2: error: ld returned 1 exit status

原因:少了靜態庫…搞了半天才解決

解決: sudo yum install glibc-static

把庫給裝上就完事了

補充:gcc -w 不生成任何警告

gcc -Wall 生成所有警告

我們預設是報警告的,所有預設是gcc -Wall

test.cpp test.cc test.cxx都表示c++檔案

gcc編譯器可以根據檔案字尾判斷檔案的程式語言
英文時間: pwd==print work directory

🍅gdb的使用🍅

什麼是gdb?

簡單來說就是偵錯程式,比如vs裡的偵錯程式

gdb 可執行程式

作用:進入偵錯

如gdb mytest

**如果報錯:**重新生成可執行檔案,gcc命令加上-g,不加預設release版本

gcc mytest -g

報錯原因:檔案裡沒有偵錯資訊,也就是我們常說的release版本

gdb介面輸入命令報錯資訊:No symbol table is loaded. Use the 「file」 command.

-g可加入偵錯資訊 ,release版本無偵錯資訊,不可被偵錯

檢查當前檔案是否具有偵錯資訊

readelf -S mytest |grep debug

效果如圖:(不列印則說明沒有debug資訊)
在這裡插入圖片描述

📖 小知識:為什麼會有debug和release?

debug是給我們開發時用的,release一般是給使用者用的

偵錯資訊也佔空間啊

如果只有debug版本,使用者又不用偵錯,偵錯資訊又多佔了程式空間

所以對使用者來說對debug的需求不強(沒有)

如果只有release版本,自己感受一下出了bug沒有偵錯程式的感覺[doge]

📖 quit(q)或者ctrl+d:退出gdb

l :顯示十行程式碼 按回車顯示十行後的程式碼

但不一定是開頭十行

📖 list (l) 行號:顯示行號所在的程式碼

📖 l 函數名 :顯示函數的程式碼

📖 b 行號:給某行加斷點 (b== Breakpoint )

如 b 7

📖 b 函數名:在函數入口加斷點

📖 info b:列出所有斷點

📖 r :開始偵錯 兩次r重新偵錯 r ==run

📖 n : 逐過程(不會進入函數) n ==next

📖 p 變數:列印變數的值,但只顯示一次

📖 print 表示式:列印表示式的值(變數也算入表示式)

📖 display 變數:長顯示,每次n都會列印

​ 比如display sum 長顯示sum,每次n都會顯示sum的值

📖 undisplay 編號 取消長顯示 注意是編號不是變數名

在這裡插入圖片描述

📖 c (continue): 跳到下一個斷點

📖 d 編號 :刪除斷點

在這裡插入圖片描述

📖 s 逐語句 :會進入函數

📖 bt :顯示呼叫堆疊

📖 until 行號 跳轉到函數裡的任意位置

和斷點有一些衝突

迴圈體:

for( i=0;i<=top;i++)
{
(斷點)	 sum+=i;//斷點啟用時(走到這行了用until) until未能跳出迴圈
}

📖 finish 跑完當前函數 (官方點:執行到當前函數返回,然後停下來等待命令 非main函數)

在這裡插入圖片描述

📖 c until finish :跳轉三劍客了屬於是 🗡

Enb=enable y表示斷點可用
在這裡插入圖片描述

📖 disable 斷點編號 :禁用斷點

為啥要禁用斷點呢,我不用直接刪掉不就行了

答:保留偵錯痕跡,方便多次偵錯

📖 delete breakpoint 、delete breakpoints :刪掉全部斷點

set var 變數:改變偵錯時變數的值

比如set var i=100,用的比較少

注:改變變數的值不是VS裡的條件斷點,而是直接改變往後執行

🍅Linux專案自動化構建工具 -make/Makefile🍅

make:這是一條指令

makefile/Makefile:這是一個檔案

依賴關係

gcc test.c -o test.exe
test.c
test.exe

test.exe的生成依賴於test.c

📖 touch makefile/touch Makefile

makefile裡面寫的是依賴關係和相應的操作

在這裡插入圖片描述
在這裡插入圖片描述

mytest:test.o 表示mytest依賴於test.o生成,表現出依賴關係
gcc test.o -o mytest gcc前面必須是Tab 不能是四個空格
test.o:test.s 表示test.o依賴於test.s生成,表現出依賴關係
gcc -c test.s -o test.o
test.s:test.i 表示test.s依賴於test.i生成,表現出依賴關係
gcc -S test.i -o test.s
test.i:test.c 表示test.i依賴於test.c生成,表現出依賴關係
gcc -E test.c -o test.i

📖 解釋一下這個make吧 ,相當於一次性執行了多條命令,降低了我們的偵錯的成本

如果檔案很多 寫gcc一個一個編譯連結過去成本太高

或者是軟體迭代的時候,進行測試等操作時一個一個寫gcc成本太高了

專案管理有生成檔案的,自然就有刪除檔案的

📖 刪除檔案時makefile這麼寫:

在這裡插入圖片描述
在這裡插入圖片描述

📖 .PHONY:clean又是什麼東西???

.PHONY很像一個宣告,宣告一下clean,或者說修飾一下clean

.PHONY定義偽目標,被修飾的clean總是被執行

⌨ 總是被執行?那肯定就有總是不被執行了

預設:總是不被執行

下面的make就是總是不被執行,即只能被執行一次,也一直提示make: `mytest’ is up to date.

同時對比clean
在這裡插入圖片描述

看到這還有一個問題

📖 為什麼生成檔案時只需要輸入「make」而我在刪除檔案時卻要輸入「make clean」?

因為make就是從makefile檔案由上往下走,執行第一條命令

這麼說很晦澀,舉個例子
在這裡插入圖片描述

全稱就應該寫 make mytest,只不過mytest相關命令寫在clean前面,所以可以簡寫為make

如果把clean寫在第一行,那make命令執行的就是刪除功能了,有興趣可以試試
此外make命令不會檢查檔案是否存在,找不到操作的檔案就直接報錯退出了

🍅簡寫makefile檔案🍅

  1 mytest:test.o
  2   gcc $^ -o $@      $@依賴於$^,類似於代指
  3 test.o:test.s
  4   gcc -c $^ -o $@
  5 test.s:test.i
  6   gcc -S $^ -o $@
  7 test.i:test.c
  8   gcc -E $^ -o $@

在這裡插入圖片描述

末尾 📖

如果有幫助的話麻煩點個贊鼓勵一下!