pimpl idiomは、ABIとの互換性を損なうことなく、ライブラリに依存するすべてのコードを再コンパイルすることなく、動的にリンクされたライブラリのコードを変更できるようにするためによく使用されます。プライベートメンバー変数を追加するとC++ ABIとの互換性が損なわれますか?
ほとんどのexplanations新しいプライベートメンバー変数を追加すると、そのクラスのパブリックメンバーとプライベートメンバーのオフセットが変更されることに言及します。それは私には意味がある。私が理解できないことは、実際にはこれが実際に依存するライブラリをどのように破壊するかということです。
私はELFファイルと動的リンクの実際の動作について多くの読書をしましたが、共有ライブラリのクラスサイズを変更することでどのように物事が損なわれるかはまだ分かりません。
など。ここでは、テストアプリケーション(a.outが)私は、テスト共有ライブラリ(libInterface.so)からコード(Interface::some_method
)を使用して書いている:
[email protected]:~/pimpl$ objdump -d -j .text a.out
08048874 <main>:
...
8048891: e8 b2 fe ff ff call 8048748 <[email protected]>
some_method
への呼び出しは、手続きリンクテーブル(PLT)を使用しています。
[email protected]:~/pimpl$ objdump -d -j .plt a.out
08048748 <[email protected]>:
8048748: ff 25 1c a0 04 08 jmp *0x804a01c
804874e: 68 38 00 00 00 push $0x38
8048753: e9 70 ff ff ff jmp 80486c8 <_init+0x30>
:
[email protected]:~/pimpl$ readelf -x 24 a.out
Hex dump of section '.got.plt':
0x08049ff4 089f0408 00000000 00000000 de860408 ................
0x0804a004 ee860408 fe860408 0e870408 1e870408 ................
0x0804a014 2e870408 3e870408 4e870408 5e870408 ....>...N...^...
0x0804a024 6e870408 7e870408 8e870408 9e870408 n...~...........
0x0804a034 ae870408 ....
そしてこれがある場合、動的リンカーWO LD_LIBRARY_PATHの共有ライブラリに含まれるすべてのシンボルを調べ、libInterface.so内にあるInterface::some_method
を見つけて、そのコードをGOTにロードします。そのため、後でsome_method
を呼び出すと、GOTのコードは実際に共有からのコードセグメントになりますとしょうかん。
またはこれらの行に沿ったもの。
しかし、私はまだ共有libのクラスサイズまたはそのメソッドのオフセットがどのように再生されるのか分かりません。私が知る限り、上記のステップはクラスのサイズには無関心です。ライブラリ内のメソッドのシンボルだけがa.outに含まれているようです。クラスのサイズの変更は、リンカがコードをGOTにロードするときに実行時に解決する必要がありますか?
私はここで何が欠けていますか?
Aha!とった。実際、Interfaceのctorが呼び出される前に逆アセンブリを少し見上げると、オブジェクトのスペース(この場合は4bytes)を割り当てることができます。 – adg