2009-02-27 59 views
114

,和__FUNCTION__使用。假定你的C++編譯器支持他們,是有什麼特別的原因使用__FILE____LINE____FUNCTION__用於記錄和調試的目的呢?__FILE__,__LINE__在C++

我主要關心的是給用戶帶來誤導性數據 - 例如,報告不正確的行號或功能作爲優化的結果 - 或因此導致性能下降。

基本上,我可以信任__FILE____LINE____FUNCTION__總是做正確的事?

+0

__LINE__應該做正確的事情。我廣泛使用了它及其同類,包括__PRETTY_FUNCTION__。 ......但是......好吧,我現在正在查看__LINE__所在的代碼。可能是因爲它在try/catch異常處理的catch塊中。 – 2012-10-11 05:08:24

+2

相關:[預定義宏的gcc參考](http://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html) – 2012-11-02 08:43:18

回答

140

__FUNCTION__是非標準的,__func__存在於C99/C++ 11中。其他人(__LINE____FILE__)都很好。

它會始終報告正確的文件和行(如果您選擇使用__FUNCTION__/__func__)則會報告正確的文件和行。優化是一個非因素,因爲它是編譯時宏擴展;它會永不以任何方式影響性能。

+2

`__func__`在C++中是一個問題。 C99並沒有對默認參數等進行說明,在`__func__`應該如何在C++中表現的情況下並不那麼明顯。 – wilhelmtell 2012-01-29 03:17:46

+3

@thr:雖然你說得很好。我清楚地知道`__func__`存在於c99中,而不是C++。無論如何,我認爲在C++中合理實現`__func__`只會導致錯誤的名稱。由於我不是編譯器編寫者,所以不是我的電話。 – 2012-04-05 03:13:16

+0

什麼編譯器根本不支持`__FUNCTION__`?除最近的gcc以外,哪些編譯器將此視爲變量,而不是宏? – basin 2013-01-18 09:11:21

7

就個人而言,我不願意使用這些除了調試消息。我已經做到了,但我儘量不向客戶或最終用戶展示那種信息。我的客戶不是工程師,有時不懂電腦。我可能會將這些信息記錄到控制檯,但是,正如我所說的,除了調試版本或內部工具外,不情願。不過,我認爲這取決於您擁有的客戶羣。

30

在極少數情況下,將__LINE__給出的行更改爲其他內容可能會有用。我已經看到GNU配置對於某些測試來說,在原始源文件中沒有出現的行之間插入一些voodoo之後,報告適當的行號。例如:

#line 100 

將使以下行以__LINE__ 100可以選擇添加一個新的文件名

#line 100 "file.c" 

這只是很少有用。但如果需要的話,我不知道有什麼替代方案。實際上,也可以使用一個宏,而不是該行,這必須導致上述兩種形式中的任何一種。使用升壓預處理庫,您可以通過增加50當前行:

#line BOOST_PP_ADD(__LINE__, 50) 

我認爲這是有益的提到它,因爲你問起__LINE____FILE__使用。一個從來沒有得到足夠的驚喜出來的C++ :)

編輯: @Jonathan萊弗勒提供了一些更良好的使用情況的意見:

與#行梅辛是非常有用的預處理器是希望保持用戶的C代碼中報告的錯誤符合用戶的源文件。 Yacc,Lex和ESQL/C預處理器(對我來說更多)。

22

供參考:g ++提供了非標準__PRETTY_FUNCTION__宏。直到現在我還不知道C99 __func__(感謝Evan!)。我認爲當它可用於額外的類作用域時,我仍然更喜歡__PRETTY_FUNCTION__。

PS:

static string getScopedClassMethod(string thePrettyFunction) 
{ 
    size_t index = thePrettyFunction . find("("); 
    if (index == string::npos) 
    return thePrettyFunction; /* Degenerate case */ 

    thePrettyFunction . erase(index); 

    index = thePrettyFunction . rfind(" "); 
    if (index == string::npos) 
    return thePrettyFunction; /* Degenerate case */ 

    thePrettyFunction . erase(0, index + 1); 

    return thePrettyFunction; /* The scoped class name. */ 
} 
4

我用他們所有的時間。我唯一擔心的是在日誌文件中放棄IP。如果你的功能名稱真的很好,你可能會更容易發現一個商業祕密。這有點像帶調試符號,只是更難找到東西。在99.999%的情況下,沒有什麼不好的。