天天看點

不常見但是很有用的 gcc 指令行選項(一)

軟體工具通常情況下會提供多個功能以供選擇,但是如你所知的,不是所有的功能都能被每個人用到的。公正地講,這并不是設計上的錯誤,因為每個使用者都會有自己的需求,他們隻在他們的領域内使用該工具。然而,深入了解你所使用的工具也是很有益處的,因為你永遠不知道它的某個功能會在什麼時候派上用場,進而節省下你寶貴的時間。

舉一個例子:編譯器。一個優秀的程式設計語言編譯器總是會提供極多的選項,但是使用者一般隻知道和使用其中很有限的一部分功能。更具體點來說,比如你是 c 語言開發人員,并将 linux 作為你的開發平台,那麼你很有可能會用到 gcc 編譯器,這個編譯器提供了 (幾乎) 數不清的指令行選項清單。

你知道,你可以讓 gcc 儲存每個編譯階段的輸出嗎?你知道用于生成警告的 <code>-wall</code> 選項,它并不會包含一些特殊的警告嗎?gcc 的很多指令行選項都不會經常用到,但是它們在某些特定的情況下會變得非常有用,例如,當你在調試代碼的時候。

是以在本文中,我們會介紹這樣的幾個選項,提供所有必要的細節,并通過簡單易懂的例子來解釋它們。

但是在開始前,請注意本文中所有的例子所使用的環境:基于 ubuntu 16.04 lts 作業系統,gcc 版本為 5.4.0。

<a target="_blank"></a>

你知道在通過 gcc 編譯 c 語言代碼的時候大體上共分為四個階段嗎?分别為預處理 -&gt; 編譯 -&gt; 彙編 -&gt; 連結。在每個階段之後,gcc 都會産生一個将移交給下一個階段的臨時輸出檔案。但是生成的都是臨時檔案,是以我們并不能看到它們——我們所看到的隻是我們發起編譯指令,然後它生成的我們可以直接運作的二進制檔案或可執行檔案。

但是比如說在預處理階段,如果調試時需要檢視代碼是如何進行處理的,你要怎麼做呢?好消息是 gcc 編譯器提供了相應的指令行選項,你可以在标準編譯指令中使用這些選項獲得原本被編譯器删除的中間檔案。我們所說的選項就是<code>-save-temps</code>。

永久存儲臨時的中間檔案,将它們放在目前的檔案夾下并根據源檔案名稱為其命名。是以,用 <code>-c -save-temps</code> 指令編譯 foo.c 檔案時會生成 foo.i foo.s 和 foo.o 檔案。即使現在編譯器大多使用的是內建的預處理器,這指令也會生成預處理輸出檔案 foo.i。 當與 <code>-x</code> 指令行選項結合使用時,<code>-save-temps</code> 指令會避免覆寫與中間檔案有着相同擴充名的輸入源檔案。相應的中間檔案可以通過在使用 <code>-save-temps</code> 指令之前重命名源檔案獲得。

以下是怎樣使用這個選項的例子:

<code>gcc -wall -save-temps test.c -o test-exec</code>

下圖為該指令的執行結果,驗證其确實産生了中間檔案:

不常見但是很有用的 gcc 指令行選項(一)

是以,在截圖中你所看到的 test.i、test.s、 test.o 檔案都是由 <code>-save-temps</code> 選項産生的。這些檔案分别對應于預處理、編譯和連結階段。

讓我們開始調試之路吧!為了能在代碼調試中使用 gdb,你需要在編譯代碼的時候使用 gcc 編譯器提供的 <code>-g</code> 選項。這個選項讓 gcc 生成 gdb 需要的調試資訊進而能成功地調試程式。

gcc 允許在使用 <code>-g</code> 選項的時候配合使用 <code>-o</code> 選項。優化代碼采用的便捷方式有時可能會産生意想不到的結果:某些你聲明的變量可能不複存在;控制流可能會突然跳轉到你未曾預期的位置;一些語句也許不會執行,因為它們已經把常量結果計算了或值已經被儲存;一些語句可能會在不同地方執行,因為它們已經被移出循環。 然而優化的輸出也是可以調試的。這就使得讓優化器可以合理地優化或許有 bug 的代碼。

注意:<code>-g</code> 和 <code>-pg</code> 選項的用法類似于上一節中使用 <code>-save-temps</code> 選項的方式。

原文釋出時間為:2017-12-09

本文來自雲栖社群合作夥伴“linux中國”

繼續閱讀