簡體   English   中英

__FILE__、__LINE__ 和 __FUNCTION__ 在 C++ 中的用法

[英]__FILE__, __LINE__, and __FUNCTION__ usage in C++

假設您的 C++ 編譯器支持它們,是否有任何特殊原因使用__FILE____LINE____FUNCTION__進行日志記錄和調試?

我主要關心的是向用戶提供誤導性數據——例如,報告不正確的行號或作為優化結果的函數——或者因此而導致性能下降。

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

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

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

在極少數情況下,將__LINE__給出的行更改為其他內容會很有用。 我已經看到 GNU configure 為某些測試執行此操作,以便在未出現在原始源文件中的行之間插入一些伏都教之后報告適當的行號。 例如:

#line 100

將使以下幾行以__LINE__ 100 開頭。您可以選擇添加新的文件名

#line 100 "file.c"

它只是很少有用。 但如果需要的話,我知道沒有其他選擇。 實際上,代替行,也可以使用宏,它必須導致上述兩種形式中的任何一種。 使用 boost 預處理器庫,您可以將當前行增加 50:

#line BOOST_PP_ADD(__LINE__, 50)

我認為提及它很有用,因為您詢問了__LINE____FILE__的用法。 從 C++ 中你永遠不會得到足夠的驚喜 :)

編輯: @Jonathan Leffler 在評論中提供了一些更好的用例:

對於希望將用戶 C 代碼中報告的錯誤與用戶的源文件保持一致的預處理器來說,使用 #line 非常有用。 Yacc、Lex 和(對我來說更熟悉)ESQL/C 預處理器可以做到這一點。

僅供參考: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. */
}

C++20 std::source_location

C++ 終於添加了一個非宏選項,當 C++20 普及時,它可能會在未來的某個時候占據主導地位:

文檔說:

constexpr const char* function_name() const noexcept;

6 返回:如果此對象表示函數體中的一個位置,則返回一個實現定義的 NTBS,該 NTBS 應與函數名稱相對應。 否則,返回一個空字符串。

其中 NTBS 表示“空終止字節字符串”。

當支持到達 GCC 時,我會嘗試一下,帶有g++-9 -std=c++2a GCC 9.1.0 仍然不支持它。

https://en.cppreference.com/w/cpp/utility/source_location聲明用法如下:

#include <iostream>
#include <string_view>
#include <source_location>

void log(std::string_view message,
         const std::source_location& location std::source_location::current()
) {
    std::cout << "info:"
              << location.file_name() << ":"
              << location.line() << ":"
              << location.function_name() << " "
              << message << '\n';
}

int main() {
    log("Hello world!");
}

可能的輸出:

info:main.cpp:16:main Hello world!

__PRETTY_FUNCTION__ vs __FUNCTION__ vs __func__ vs std::source_location::function_name

回答: __PRETTY_FUNCTION__、__FUNCTION__、__func__ 之間有什么區別?

就個人而言,除了調試消息之外,我不願意將它們用於任何其他用途。 我已經做到了,但我盡量不向客戶或最終用戶顯示此類信息。 我的客戶不是工程師,有時也不精通計算機。 我可能會將此信息記錄到控制台,但正如我所說,除了調試版本或內部工具之外,我很不情願。 不過,我想這確實取決於您擁有的客戶群。

我一直在使用它們。 我唯一擔心的是在日志文件中泄露 IP。 如果您的函數名稱非常好,您可能會使商業秘密更容易被發現。 這有點像附帶調試符號,只是更難找到東西。 在 99.999% 的情況下,不會有什么不好的事情發生。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM