web-dev-qa-db-ja.com

C ++での名前マングリングに関する質問

私はC++での名前マングリングを学び理解しようとしています。ここにいくつかの質問があります:

(1)From devx

グローバル関数がオーバーロードされると、オーバーロードされたバージョンごとに生成されるマングル名は一意になります。名前マングリングは変数にも適用されます。したがって、同じユーザー指定の名前を持つローカル変数とグローバル変数は、依然として別個のマングル名を取得します。

オーバーロード関数と同じ名前のグローバル変数とローカル変数以外に、名前マングリングを使用している他の例はありますか?

(2)From Wiki

言語が、異なる名前空間を占有している限り、異なるエンティティに同じ識別子で名前を付けることができる場合に必要になります(名前空間は通常、モジュール、クラス、または明示的な名前空間ディレクティブによって定義されます)。

オーバーロード関数は同じ名前空間にあり、同じ名前のグローバル変数とローカル変数も同じスペースにある可能性があるため、名前マングリングが識別子が異なる名前空間に属する場合にのみ適用される理由はよくわかりません。これを理解する方法は?

同じ名前でスコープが異なる変数も名前マングリングを使用しますか?

(3)Cには名前マングリングがありますか?そうでない場合、一部のグローバル変数とローカル変数が同じ名前の場合にどのように対処できますか? Cにはオーバーロード機能がありませんよね?

ありがとう、よろしく!

23
Tim

Cは名前のマングリングを行いませんが、関数名の前にアンダースコアを付けるため、printf(3)は実際にはlibcオブジェクトの__printf_です。

C++では、話は異なります。その歴史は、もともとStroustrupが「Cwithclasses」または cfront を作成したことです。これは、初期のC++をCに変換するコンパイラです。その後、残りのツール-Cコンパイラとリンカーを使用してオブジェクトを生成しました。コード。これは、C++名を何らかの方法でC名に変換する必要があることを意味していました。これはまさに 名前マングリング が行うことです。各クラスメンバーとグローバル/名前空間関数および変数に一意の名前を提供するため、名前空間とクラス名(解決用)および引数タイプ(オーバーロード用)が最終的なリンカー名に何らかの形で含まれます。

これは、 nm(1) --C++ソースをコンパイルし、生成されたシンボルを確認するなどのツールで非常に簡単に確認できます。以下は、GCCを使用するOSXです。

_namespace zoom
{
    void boom( const std::string& s )
    {
        throw std::runtime_error( s );
    }
}

~$ nm a.out | grep boom
0000000100001873 T __ZN4zoom4boomERKSs
_

CとC++の両方で、ローカル(自動)変数はシンボルを生成しませんが、レジスターまたはスタックに存在します。

編集:

ローカル変数は、リンカがそれらについて知る必要がないという理由だけで、結果のオブジェクトファイルに名前がありません。だから名前もマングリングもありません。他のすべて(リンカーが調べなければならない)は、C++では名前が壊れています。

27

マングリングは、コンパイラーがリンカーを幸せに保つ方法です。

Cでは、何があっても同じ名前の2つの関数を持つことはできません。これが、リンカが想定するように記述されたものです。一意の名前です。 (静的関数の名前はリンカーにとって重要ではないため、異なるコンパイル単位で静的関数を使用できます。)

C++では、パラメーターの種類が異なる限り、同じ名前の2つの関数を使用できます。したがって、C++は、関数名と型を何らかの方法で組み合わせます。そうすれば、リンカはそれらを異なる名前を持つものとして認識します。

名前がどのようにマングルされるかは問題ではなく、実際、コンパイラーごとに異なる方法で行われることに注意してください。重要なのは、同じベース名を持つすべての関数が何らかの形でリンカーに対して一意になっていることです。

名前空間とテンプレートをミックスに追加すると、原則が拡張され続けることがわかります。

19
egrunin

技術的には、それは「装飾」です。粗雑ではないように聞こえますが、マングリングのようなものは、CreditInterestIntCrederestitに再配置される可能性があることを意味しますが、実際に発生するのは_CreditInterest@4に似ており、より「装飾」されていると言っても過言ではありません。壊れたより。そうは言っても、私もそれをマングリングと呼んでいます:-)しかし、「C++の名前の装飾」を検索すると、より技術的な情報と例を見つけることができます。

9
Kate Gregory

オーバーロード関数と同じ名前のグローバル変数とローカル変数以外に、名前マングリングを使用している他の例はありますか?

C++マングルallシンボル、常に。コンパイラにとっては簡単です。通常、マングルは、必要とされるマングルの最も一般的な原因であるため、パラメータリストまたはタイプに関する何かをエンコードします。

Cはマングルしません。スコープは、同じ名前のローカル変数とグローバル変数へのアクセスを制御するために使用されます。

5
Donnie

出典: http://sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html

名前マングリングは、C++コンパイラが使用するプロセスであり、プログラム内の各関数に一意の名前を付けます。 C++では、通常、プログラムには少なくとも同じ名前の関数がいくつかあります。したがって、名前マングリングはC++の重要な側面と見なすことができます。

例:通常、メンバー名は、メンバーの名前をクラスの名前と連結することによって一意に生成されます。宣言が与えられた:

class Class1
 {
        public:
            int val;
            ...
  };

valは次のようになります。

  // a possible member name mangling
 val__11Class1
2
Santosh

agner には、名前マングリングとは何か、およびさまざまなコンパイラでどのように行われるかについての詳細があります。

名前マングリング(名前装飾とも呼ばれます)は、C++コンパイラーが、オブジェクトファイル内の関数およびオブジェクトの名前に追加情報を追加するために使用する方法です。この情報は、あるモジュールで定義された関数またはオブジェクトが別のモジュールから参照されるときにリンカーによって使用されます。名前マングリングは次の目的を果たします。

  1. リンカがオーバーロードされた関数の異なるバージョンを区別できるようにします。
  2. リンカが、オブジェクトと関数がすべてのモジュールでまったく同じ方法で宣言されていることを確認できるようにします。
  3. リンカがエラーメッセージで未解決の参照のタイプに関する完全な情報を提供できるようにします。

名前マングリングは、目的1を実現するために考案されました。その他の目的は、すべてのコンパイラで完全にサポートされているわけではない二次的な利点です。関数に提供する必要のある最小限の情報は、関数の名前とそのすべてのパラメーターのタイプ、およびクラスまたは名前空間の修飾子です。可能な追加情報には、戻り値の型、呼び出し規約などが含まれます。この情報はすべて、人間の観察者にはわかりにくいように見える単一のASCIIテキスト文字列にコード化されます。リンカーは、これが何であるかを知る必要はありません。コードとは、目的1と2を実行することを意味します。文字列が同一であるかどうかを確認するだけで済みます。

0
cpp_enthusiast