1

私は現在、特にデバッグ中に STL コンテンツを印刷するために、STL についていくつかの調査を行っています。私は多くの異なるアプローチがあることを知っています。

お気に入り:

私が現在探しているのは、g ++が使用されていない関数を削除する理由です。たとえば、次のコードがあり、コンパイル設定を使用していますg++ -g main.cpp -o main.o

include <vector>
include <iostream>
using namespace std;
int main() {
    std::vector<int> vec;
    vec.push_back(10);
    vec.push_back(20);
    vec.push_back(30);

    return;
}

したがって、このコードをデバッグすると、使用できないことがわかりますprint vec.front()。私が受け取るメッセージは次のとおりです。

Cannot evaluate function -- may be inlined

したがって、設定を使用しようとしました-fkeep-inline-functionsが、変更はありません。

使用するnm main.o | grep frontと、メソッドの行エントリがないことがわかります.front()。同じことをもう一度行いますがvec.front()、コード内に追加のエントリを使用して、エントリが表示される場所をprint vec.front()使用して使用できますnm main.o | grep front

0000000000401834 W _ZNSt6vectorIiSaIiEE5frontEv

すべての関数を失わずにコード内に保持する方法を誰かに説明してもらえますか? 私は、最適化設定を設定したり、以下を実行したりしない限り、デッド関数は削除されないと思います。

必要な理由: 現在の Python 実装では、内部 STL 実装を使用してコンテナーのコンテンツを出力しますが、ISO/IEC 14882 で定義されている関数を使用する方がはるかに興味深いでしょう。共有ライブラリを作成できることはわかっています。デバッグする前に実際のコードにコンパイルして、すべての STL 関数があることを維持できますが、デバッグする前に追加の lib をそのコードにコンパイルしたい場合。この 2 つのアプローチ (Shared Lib. と Python) の長所と短所があるかどうかを知ることも興味深いでしょうか?

4

2 に答える 2

4

デッド関数とは正確には、ソース コードで使用できるが使用されていない関数ではありませんか?

考慮すべき 2 つのケースがあります。

int unused_function() { return 42; }
int main() { return 0; }

上記のプログラムをコンパイルすると、unused_functionは死んでおり、呼び出されることはありません。ただし、最終的な実行可能ファイルにはまだ存在します (最適化 [1] を使用しても)。

これを考慮してください:

template <typename T> int unused_function(T*) { return 42; }
int main() { return 0; }

この場合、すべての最適化をオフにしても、存在しunused_functionません。

なんで?テンプレートは「実際の」関数ではないためです。これは、コンパイラが「実際の」関数 (「テンプレートのインスタンス化」と呼ばれる) を作成できるプロトタイプTです。を使用したことがないためunused_function、コンパイラはその「実際の」インスタンスを作成しませんでした。

次のように、コンパイラが特定のクラスのすべてのexplicit instantiation request関数を明示的にインスタンス化するように要求できます。

#include <vector>
template class std::vector<int>;

int main() { return 0; }

現在、関数は使用されていませんが、それらはすべて最終的なバイナリにインスタンス化されています。vector

[1] GNU ld(または) を使用している場合でも、 でコンパイルしてリンクするgoldことで、この場合は取り除くことができます。unused_function-ffunction-sections-Wl,--gc-sections

于 2012-06-09T14:23:57.613 に答える
0

ご回答有難うございます。繰り返しになりますが、テンプレート関数はプロトタイプであるため、gccによって開始されません。関数が使用されているか、明示的に開始された場合にのみ、実行可能ファイル内で使用できます。

だから私たちがまだ言及したことは:

  • 関数定義 intunusedFunc(){return 10; }
  • 関数プロトタイプ intprotypeFunc(); (それを分解するためだけに)

インライン関数を使用するとどうなりますか?関数はソースコード内に挿入されるといつも思っていましたが、今読んだところ、コンパイラーが自分で何をするかを決めることがよくあります。(彼らはルールでなければならないので、奇妙に聞こえます)。たとえば、キーワードinlineを使用するかどうかは関係ありません。

inline int inlineFunc() { return 10; }

私の友人はまた、彼はインラインを使用していませんが、関数のアドレスにアクセスできなかったと私に言いました。忘れた関数型はありますか?彼はまた、それらはオブジェクトデータ形式内の違いであるべきだと私に言いました。

@編集-忘れた:

  • 入れ子関数
  • 関数ポインタ
  • オーバーロードされた関数
于 2012-06-14T16:47:35.837 に答える