在C11

2012-12-03 44 views
13

使用_Noreturn的可能重複:
What is the point of the Noreturn attribute?在C11

C11引入了_Noreturn屬性指示函數永遠不會返回。

除了源代碼中的文檔值外,該屬性還提供了哪些其他好處,以及爲什麼要使用它?

+1

http://stackoverflow.com/questions/10538291/what-is-the-point-of-the-noreturn-attribute對C++提出同樣的問題。 C的推理完全一樣。 –

+3

推理類似;在C++('[[noreturn]]')和C('_Noreturn'或'noreturn',如果包含''')之間,語法看起來完全不同。所以,我認爲這是一個很好的x-ref;不過,我不確定是否有重複。 –

+2

提名重新開放,因爲這是關於C的,另一個是關於C++的兩種完全不同的語言。實際的語法也非常不同。 –

回答

18

如果一個函數調用無條件一個_Noreturn函數,編譯器將能夠認識到:

  • 下面是死代碼的代碼,這使得優化(可以從生成的二進制被刪除)和診斷 - 編譯器將能夠發出「不可達的代碼」警告;
  • 最重要的是,知道來自函數的正常流被中斷,它將能夠避免關於缺少返回值,未初始化的變量等的虛假警告。

    這是靜態代碼分析尤爲重要 - 在我們的一個較大的應用程序通過鐺靜態分析給出誤報的數量大幅下降,一旦我們標誌着我們die功能(記錄一個致命錯誤並終止應用程序)爲noreturn

也可以有一些可用的其他優化 - 因爲該函數永遠不會返回,沒有必要推的返回地址在堆棧中,保存寄存器的狀態和任何,所有需要被傳遞參數並在函數的開始執行jmp,而不必擔心返回和返回後清理。但是,當然,由於這次電話會議是一次性的,所以這裏的表現幾乎可以忽略不計。

+0

通過這個參數,即使返回的函數可能被標記爲_Noreturn,對吧?例如:'int foo(data * arg){++ arg-> count;返回欄(arg); }' - 可以通過跳轉調用函數foo,然後再跳到實際返回數據的bar()。或者我錯過了這一點? – user666412

+0

@ user666412:這是尾巴呼叫優化,這是最不相關的。將'_Noreturn'應用於'bar'意味着它永遠不會返回; OTOH,在這裏編譯器可能只是在一個特定的實例中將清理委託給'bar'。另外,回想起來,我的回答過於強調優化方面(這對於'_noreturn'函數來說很勉強,因爲它們顯然很少被調用),重點主要是標記死代碼並更好地定製這些環境中的警告調用(例如,如果我有一個函數「退出(1)」,它是否與返回無關)。 –

+0

對於一次在程序中最多隻會發生一次的呼叫,似乎仍然過於費力。 – user666412

0

它允許編譯器進行其他優化。採取在GCC的noreturn屬性一看here它支持現在一段時間(語義可能是相同的)

4

__attribute__((noreturn))_Noreturn是功能非常有用像die()

static __attribute__((noreturn)) void die(const char *fmt, ...) { 
    /* print a formatted error message and exit */ 
    exit(EXIT_FAILURE); 
} 
/* And let's say in main() you would want to exit because of an error but unforunately GCC complains about return value. */ 
int main() 
{ 
    if (!whatever) 
     die("a nasty error message goes here\n"); 
} 

而且也用於優化作爲說明。

+0

[JFYI]您不需要從main()函數明確「返回」(這是C兼容性的殘餘) – AlexT

+0

這僅僅是一個示例來說明會發生什麼。 – 2014-02-03 08:30:10