47

I know that inline function are either replaced where it is called or behave as a normal function.

But how will I know whether inline function is actually replaced at the place where it is called or not as decision of treating inline function as inline is at the compile time?

4

10 に答える 10

71

実行時にプログラムで、できません。
そして、問題の真実は次のとおり です。あなたは知る必要はありません

inlineコンパイラは、マークされていない関数を選択するか、inline明示的にマークされている関数を無視することを選択できますinline。これは完全にコンパイラの願いです (知恵を読む) & コンパイラがその仕事を慎重に行うことを信頼する必要があります。主流のコンパイラのほとんどは、うまく機能します。

質問が純粋に学術的な観点からのものである場合は、いくつかの選択肢があります。


生成されたアセンブリ コードを分析します。

アセンブリ コードをチェックして、呼び出し時に関数コードがインライン化されているかどうかを確認できます。

アセンブリ コードを生成する方法

gcc の場合:コンパイル中にスイッチを
使用します。 例:-S

g++ -S FileName.cpp

生成されたアセンブリ コードは、 file として作成されますFileName.s

MSVC の場合:コマンド ラインから/FA スイッチ
を 使用します。

生成されたアセンブリ コードcallで、特定の関数のアセンブリ命令があるかどうかを調べます。


コンパイラ固有の警告と診断を使用します。

一部のコンパイラは、インライン関数要求に準拠しない場合に警告を発します。
たとえば、gcc では、-Winlineインラインで宣言された関数をコンパイラがインライン化しない場合、コマンド オプションは警告を発します。

詳細については、 GCC のドキュメントを確認してください。

-ウィンライン

インラインとして宣言された関数をインライン化できない場合に警告します。このオプションを使用しても、コンパイラは、システム ヘッダーで宣言された関数のインライン化の失敗について警告しません。

コンパイラは、さまざまなヒューリスティックを使用して、関数をインライン化するかどうかを決定します。たとえば、コンパイラは、インライン化される関数のサイズと、現在の関数で既に実行されたインライン化の量を考慮します。したがって、ソース プログラムの一見取るに足らない変更によって、 によって生成された警告が表示され-Winlineたり消えたりする可能性があります。

于 2012-05-17T07:03:38.067 に答える
12

Check the generated code. If the function is expanded, you'll see its body, as opposed to a call or similar instruction.

于 2012-05-17T07:03:10.020 に答える
9

nmLinuxなどのオブジェクトファイルからシンボルを一覧表示するためのツールを使用できます。関数がインライン化されている場合、nm出力には表示されません。他の関数の一部になりました。また、デバッガーでこの関数に名前でブレークポイントを設定することはできません。

于 2012-05-17T07:46:43.540 に答える
7

関数がインライン化されており、MS VC++ で独自の拡張機能を使用しても問題ないことを確認する必要がある場合は、 declaratorを確認してください__forceinline。コンパイラは関数をインライン化するか、文書化された特殊なケースのリストに該当する場合は警告を表示するため、インライン化のステータスを知ることができます。

いかなる方法でもそれを支持するものではありません。

于 2013-07-02T01:59:51.503 に答える
6

gdb で関数を呼び出せない場合、考えられる意味の 1 つは関数がインラインであることです。推論を反転すると、gdb 内で関数を呼び出すことができる場合、関数がインラインでマークされていないことを意味します。

于 2013-05-05T18:03:05.243 に答える
3

関数をインライン化するかどうかの決定は、コンパイラによって行われます。そして、それはコンパイラーによって作成されるため、はい、コンパイル時にのみ作成できます。

したがって、-S オプション (gcc -S を使用してアセンブリ コードを生成) を使用してアセンブリ コードを表示できれば、関数がインライン化されているかどうかを確認できます。

于 2012-05-17T07:09:01.850 に答える
1

アセンブリ コードを確認せずに、プログラムによって関数がインライン化されているかどうかを判断する方法があります。この回答はhereから取得されます。

特定の呼び出しがインライン化されているかどうかを確認したいとします。あなたはこのように行きます。コンパイラは関数をインライン化しますが、エクスポートされる (そしてほとんどすべての関数がエクスポートされる) 関数については、外部から呼び出すことができるインライン化されていないアドレス指定可能な関数コードを維持する必要があります。

関数がインライン化されているかどうかを確認するには、関数ポインター (インライン化されていない) を PC の現在の値とmy_function比較する必要があります。my_function私の環境(GCC 7、x86_64)で行った方法は次のとおりです。

void * __attribute__((noinline)) get_pc () { return _builtin_return_address(0); }

void my_function() {
    void* pc = get_pc();
    asm volatile("": : :"memory");
    printf("Function pointer = %p, current pc = %p\n", &my_function, pc);
}
void main() {
    my_function();
}

関数がインライン化されていない場合、PC の現在の値と関数ポインターの値の差は小さくなり、そうでない場合は大きくなります。私のシステムでmy_functionは、インライン化されていない場合、次の出力が得られます。

Function pointer = 0x55fc17902500, pc = 0x55fc1790257b

関数がインライン化されている場合、次のようになります。

Function pointer = 0x55ddcffc6560, pc = 0x55ddcffc4c6a

インライン化されていないバージョンの違いは0x7bであり、インライン化されたバージョンの違いは0x181fです。

于 2020-06-12T11:58:51.103 に答える