C ++での__FILE __、__ LINE__、および__FUNCTION__の使用法


158

彼らはあなたのC ++コンパイラのサポートしていることを仮定すると、特定の理由があるない使用する__FILE____LINE__および__FUNCTION__ロギングとデバッグ目的のためには?

私は主に、ユーザーに誤解を招くようなデータを与えること(例えば、最適化の結果として誤った行番号または機能を報告すること)、または結果としてパフォーマンスヒットをとることに関心があります。

基本的に、私は信頼できる__FILE____LINE____FUNCTION__するために、常に正しいことを行いますか?


LINEは正しいことをするべきです。私はそれとPRETTY_FUNCTIONを含むそのコホートを幅広く使用しました。...しかし...まあ、私はちょうど今、LINEのあるコードを調べています。おそらく、それがtry / catch例外処理のcatchブロックにあるためです。
Krazy Glew

回答:


191

__FUNCTION__非標準で__func__、C99 / C ++ 11 に存在します。その他(__LINE__および__FILE__)は問題ありません。

常に正しいファイルと行(および__FUNCTION__/ を使用することを選択した場合は機能)を報告します__func__。最適化はコンパイル時のマクロ展開であるため、重要ではありません。それは決してパフォーマンスに影響を与えません


3
__func__C ++の一種の問題です。C99はデフォルトの引数などについて語っていません__func__。C++でどのように動作するかがそれほど明確ではない場合です。
wilhelmtell 2012年

4
@thr:あなたが良い指摘をしている間。私は__func__、c ++ではなくc99に存在することをかなり明確にしました。とにかく、__func__c ++での適切な実装では、名前が壊れるだけだと思います。私はコンパイラーのライターではないので、それは実際には私の呼びかけではありません。
エヴァンテラン

どのコンパイラがまったくサポート__FUNCTION__していませんか?最近のgcc以外のコンパイラは、これをマクロではなく変数として扱いますか?
盆地

36
__func__現在はC ++ 11標準です。
VX 2013

38

まれなケースですが、指定された行を別の行に変更すると便利な場合があり__LINE__ます。GNU configureが、元のソースファイルに表示されない行の間にブードゥーを挿入した後、適切な行番号を報告するために、GNU configureがそれを実行するのを見てきました。例えば:

#line 100

次の行は__LINE__100 から始まります。オプションで新しいファイル名を追加できます

#line 100 "file.c"

それが役立つことはほとんどありません。しかし、それが必要な場合、私が知っている代替手段はありません。実際には、行の代わりにマクロを使用することもできます。その場合、上記の2つの形式のいずれかになるはずです。ブーストプリプロセッサライブラリを使用すると、現在の行を50ずつ増やすことができます。

#line BOOST_PP_ADD(__LINE__, 50)

私はそれはあなたがの使用について尋ねたので、それを言及するのに便利だと思った__LINE____FILE__。C ++から十分な驚きが得られることは決してありません:)

編集: @ジョナサン・レフラーはコメントでいくつかのより良いユースケースを提供します:

#lineでのメッシングは、ユーザーのソースコードに沿ってユーザーのCコードで報告されたエラーを保持したいプリプロセッサに非常に役立ちます。Yacc、Lex、そして(私にとってはもっと家にいる)ESQL / Cプリプロセッサーがそれを行います。


29

参考: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. */
}

2
__PRETTY_FUNCTION__について知っておくと便利です。非常に便利!
Zheng Qu

8

個人的には、デバッグメッセージ以外の目的でこれらを使用するのは気が進まない。私はそれを行いましたが、そのような情報を顧客やエンドユーザーに見せないようにしています。私の顧客はエンジニアではなく、コンピューターに精通していない場合もあります。この情報をコンソールに記録するかもしれませんが、言ったように、デバッグビルドや内部ツールを除いてしぶしぶです。でも、それはあなたが持っている顧客ベースに依存すると思います。


29
「この情報をコンソールに記録するかもしれません」-またはそれよりも良い方法:ファイルに記録して、問題が発生した場合にお客様に情報を送信するよう依頼することができます...
Christoph

7

C ++ 20 std::source_location

C ++はついに非マクロオプションを追加しました。C++ 20が普及する将来のある時点で、それが支配的になる可能性があります。

ドキュメントは言う:

constexpr const char * function_name()const noexcept;

6戻り値:このオブジェクトが関数の本文内の位置を表す場合、関数名に対応する実装定義のNTBSを返します。それ以外の場合は、空の文字列を返します。

ここで、NTBSは「Null Terminated Byte String」を意味します。

サポートがGCCに届いたら、GCC 9.1.0 g++-9 -std=c++2aがまだサポートされていないときに試してみます。

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__vsstd::source_location::function_name

回答:__PRETTY_FUNCTION __、__ FUNCTION __、__ func__の違いは何ですか?


1
あり<experimental/source_location>、現在のgcc-9で。
陈浩南

5

いつも使っています。私が心配するのは、ログファイルでIPを配布することだけです。関数名が本当に良ければ、営業秘密を明らかにしやすくなります。これは、デバッグシンボルを同梱して出荷するようなものです。99.999%のケースでは、悪いことは何も起こりません。


1
育てることの良いポイント。stringsユーティリティを使用してこの情報を抽出し、実行可能ファイルからすべての文字列のようなデータを抽出することは簡単です。圧縮された実行可能ファイルも抽出できます。お客様のサイトに送信する内容に十分注意してください。多くの場合、競合他社が実行可能ファイルを手に入れることはできませんが、そうすることは想定されていません。
2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.