2013-03-29 83 views
2

gcc內,使用當內聯函數的編譯過程

  • -E給出預處理代碼;
  • -S,彙編代碼;
  • -c,代碼已編譯但未鏈接。

有什麼接近-I,這將讓我看到是否功能已被內聯與否,即看到代碼擴展,彷彿inline函數被preporcessed宏?

如果不是,我應該通過彙編代碼,還是以後執行內聯應用程序?

回答

2

我認爲檢查彙編代碼是最好的(也是唯一的)方法來查看內聯。

請記住,在某些情況下,某些內聯可以在鏈接時發生。請參閱Can the linker inline functions?

-1

此處的問題是,通常內聯是鏈接時間優化(當存在多個對象文件時),因爲編譯器在鏈接時間之前根本沒有看到其他對象文件中函數的實現。

因此,在多目標文件編譯中,最好的辦法是檢查生成的程序集,但是在每個單獨的目標文件中,內聯是可能的,假定要內聯的函數在同一編譯單元中,但大多數編譯器不在這一點上進行內聯,因爲它不知道這個函數可能被調用的位置,以及它是否應該被內聯。

因此,通常內聯是在鏈接上執行的,但是對於非常小的函數,它可以也應該在編譯時完成。

另外我相信,如果你用clang/llvm編譯你的代碼,你會得到一個帶有內聯的c輸出文件,我沒有嘗試過。

請注意,爲了讓GCC做鏈接時間優化(包括內聯),你必須提供一個參數,我認爲它是-flto。

另一種方法是讓所有的內聯函數在您的所有編譯單元中可見(例如在頭文件中),這實際上通常會確保內聯以避免同一函數的多個聲明在不同的目標文件中。

另一種檢查程序集內聯的簡單方法是將源代碼中函數的調用次數與程序集中的調用次數進行比較。

+0

內聯可以並且也在單個翻譯單元中發生。誠然,這對'static' /'inline' /'namespace {}'函數是非常有用的,但應該內聯的很多代碼(有意)放置在那些代碼中。 – delnan

+0

大多數編譯器在編譯單個翻譯單元時都會進行內聯。從另一個模塊調用函數的事實是無關緊要的:如果函數具有外部鏈接,則編譯器既可以在單元內的調用中內聯它,也可以提供可以在外部調用的副本。 –

1

您可以使用-Winline選項來查看函數是否無法內聯並且聲明爲內聯。

http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#Warning-Options

-Winline Warn if a function that is declared as inline cannot be inlined. Even with this option, the compiler does not warn about failures to inline functions declared in system headers. The compiler uses a variety of heuristics to determine whether or not to inline a function. For example, the compiler takes into account the size of the function being inlined and the amount of inlining that has already been done in the current function. Therefore, seemingly insignificant changes in the source program can cause the warnings produced by -Winline to appear or disappear.

然而引述inline不是命令,是否inline函數或不(儘管聲明爲inline)是由編譯器決定。It may consider the size of the function being inlined and how many times inline already been done in the current function.

查看函數是否真的是inlined的最好方法是檢查彙編代碼。例如,可以使用

GCC -O2 -S -c foo.c的

生成彙編代碼foo.c和輸出組件代碼文件foo.s