我公司的一些程式員已經開始__attribute__((noinline))在我們的代碼中散布方法,包括頭檔案和源檔案。我們不使用整體程式優化。在我看到的絕大多數情況下,這些方法不會呼叫同一源檔案中的其他方法(“翻譯單元”);這些“noinline”方法的唯一呼叫者是(在大多數情況下)其他源檔案中的方法。
我想指出這些__attribute__((noinline))屬性標記沒有做任何事情,只會讓我們的代碼變得混亂,但在我這樣做之前,我只想驗證我是對的:
如果方法的定義(代碼主體)是...,將方法標記為“noinline”有什么好處?
- 在源(.c 或 .cpp)檔案中
- 未被該源檔案中的任何其他方法呼叫
- 并且沒有使用整個程式優化
...?
即,在沒有整個程式優化的情況下,編譯器 聯結器甚至可以行內這樣定義的方法(在專案符號之上)嗎?
uj5u.com熱心網友回復:
如果方法的定義(代碼主體)是...,將方法標記為“noinline”有什么好處?
- 在源(.c 或 .cpp)檔案中
- 未被該源檔案中的任何其他方法呼叫
- 并且沒有使用整個程式優化
...?
屬性在函式/方法定義上而不是在非定義宣告上的位置在屬性的特定情況下不一定相關noinline,因為為了執行行內,函式定義的某種形式(它帶有屬性)必須可用。
當然,如果該單元中沒有其他函式首先直接或間接呼叫該函式,則該函式不會行內到同一翻譯單元中的任何其他函式中。
“未使用整個程式優化”似乎是試圖規定所討論的函式也不能行內到任何其他函式中。在這種情況下,根據假設noinline,該屬性對于阻止該函式的行內是不必要的。
即,在沒有整個程式優化的情況下,編譯器 聯結器甚至可以行內這樣定義的方法(在專案符號之上)嗎?
這似乎是一個語意問題。我會將任何跨越翻譯單元邊界的優化歸類為“整個程式優化”。從這個意義上說,不,不執行任何整體程式優化的構建程序將不會執行將一個 TU 中的函式行內到不同 TU 的函式的特定整體程式優化。
由于您沒有指定編譯程序的任何細節,因此我們無法確定在您的特定情況下是否真的沒有使用整個程式優化,在上面描述的意義上。
但是,是否需要該屬性以防止在當前代碼庫中行內函式并不是與“有什么好處嗎?”相關的唯一考慮因素。問題。考慮:
無論該屬性是否需要防止行內,都可以有效地傳達不應行內函式的意圖。
如果您對代碼的分析是錯誤的,或者代碼更改以使其不再適用,這些
noinline屬性將提供所需的行內抑制行為。
這兩者都讓人想起斷言的性質和(正確)使用。如果我的程式中的斷言曾經觸發,那么這意味著出現了一種我認為不會發生并且假設不會發生的情況。那么斷言只是浪費代碼嗎?不,當然不是。它們服務于檔案目的(通常輔以解釋性代碼注釋)、錯誤檢測目的,并且通常用于故障保護目的。noinline在你所描述的情況下,可以說類似的使用。
uj5u.com熱心網友回復:
行內仍然可以在源檔案中發生。如果函式在定義后被呼叫,編譯器可以行內它。所以該屬性會阻止這種情況。
因此,這個屬性在源檔案中仍然可以產生有用的效果,以至于您需要關閉行內。
uj5u.com熱心網友回復:
無論優點(使用noinline與否),我都會使用宏而不是__attribute__((noinline))到處亂用。
而且,編譯器可以通過命令列禁用行內(見下文)。
在我的代碼中,我有時想要一個總是行內的函式[通常在.h檔案中定義] :
static inline __attribute__((always_inline))
這相對冗長[并且容易出錯],所以我定義:
#define inline_always static inline __attribute__((always_inline))
我不喜歡編譯器為我決定函式的行內,所以我從命令列禁用它:
-fno-inline-small-functions -fno-inline-functions-called-once -fno-inline-functions
這可能是比更改函式原型更安全/更好的選擇。
不行內未明確標記為的函式有一些優點。inline
用于除錯和斷點。
編譯器的啟發式無法生成最佳代碼:
- 它行內了一些從行內與函式呼叫開銷中幾乎沒有好處的東西。
- 行內對編譯器來說似乎很好,但呼叫函式的代碼不是最佳的,因為它會導致額外的暫存器壓力,需要更頻繁地將暫存器溢位[到堆疊]。
對于除錯,我們可以在編譯時-O0禁用編譯器行內函式。
但是,有時,我們需要能夠在經過優化編譯的gdb代碼中的函式上放置 [ ] 斷點。如果該函式已被 [auto] 行內,則這將無法正常作業 [太好]。
所以,要么使用-fno-inlineet。人。或將宏應用于關鍵功能,如下所示:
#ifdef DEBUG_NOINLINE
#define noinline_debug __attribute__((noinline))
#else
#define noinline_debug /**/
#endif
請注意,Linux 內核使用這樣的宏:
#define noinline __attribute__((noinline))
#define __always_inline inline __attribute__((__always_inline__))
這在給定編譯器不支持特定屬性的情況下很有用:
#if __has_attribute(__nonstring__)
# define __nonstring __attribute__((__nonstring__))
#else
# define __nonstring
#endif
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/513852.html
標籤:C C
