マングリング
name mangling
コンパイラ が関数名を一意に識別するために関数名に変更を加えること 登場した経緯
どのオブジェクトファイルを結びつけるかは、名前が一致するかだけで判断している(名前解決) そのため、C では関数や変数はグローバルな 名前空間 で管理され、名前が一意であることが求められる (この結果、C 言語のライブラリではすべての関数に接頭辞を付けるのが慣習となった)
e.g. lib1_process と lib2_process
しかし、C++ では オーバーロード や名前空間などの新機能が導入されたことで、この方法では対応できなくなった e.g.
code:cpp
namespace ns1 {
int32_t add(int32_t a, int32_t b) { return a+b; }
int64_t add(int64_t a, int64_t b) { return a+b; }
}
namespace ns2 {
int32_t_add(int32_t a, int32_t b) { return a+b; }
}
これを解決するために登場したのがマングリング
これにより、リンカによる オブジェクトファイル 同士を結び付ける処理はそのままに、対応できるようになった オブジェクトファイルに対して nm コマンドを用いると、リンカが動作する対象を確認することができる code:sh
# gcc(C)で生成したオブジェクトファイルの場合
$ nm lib.o | grep add
0000000000000000 T _add
# g++(C++)で生成したオブジェクトファイルの場合
$ nm cpp-lib.o | grep add
0000000000000000 T __Z3addii
C++ の場合の出力結果を見ると、マングリングされていることが確認できる
c++filt コマンドを用いると、マングリングされた関数名を可読な C++ のコードに戻してくれる code:sh
$ nm cpp-lib.o | grep add | c++filt
0000000000000000 T add(int, int)
参考