問題タブ [vptr]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - vptr が仮想関数を持つクラスのメモリの最初のエントリとして格納されるのはなぜですか?
一部のコンパイラでは、クラスに仮想関数がある場合、そのオブジェクトの最初のバイトのアドレスを使用してその vptr にアクセスできます。例えば、
さまざまなコンパイラの動作に依存していることはわかっています。一番最初のエントリとして vptr が格納される場合があるので、これを行う利点は何ですか? それはパフォーマンスの向上に役立ちますか、それとも単に &b を使用して vbtl にアクセスする方が簡単だからですか?
c++ - 仮想関数を持つクラスが、仮想関数を持たないクラスと異なる方法で配置されるのはなぜですか?
Richard Powellによるこのcppcon トークに触発されて、次のコード スニペットを作成しました。
これは次のように出力されます:
に追加virtual
した後who()
、これを取得します
構造体に のサイズを追加するのvoid*
は簡単ですが、非仮想の場合ではなく、仮想の場合にこのパディング (Richard の講演でも言及されています) があるのはなぜでしょうか?
Ubuntu 14.04 64ビットでgcc 5.3.0とclang 3.7.1でテストしました
c++ - 多重継承時のオブジェクト構築と仮想ポインタ
Test オブジェクトのサイズは 8 バイトです。したがって、この例から、オブジェクトが 2 つの 4 バイトの _vptr で構成されていることが明らかです。継承の順序はpublic Base1,public Base2
次のとおりであるため、オブジェクトは次のように作成する必要があります。
しかし、コード スニペットから、オブジェクトは次のように作成されているように見えます。
最初の vptr は、3 つの関数ポインター (1 番目のポイントBase1::fun1()
、2 番目のポイント、Base1::func1()
および 3 番目のポイント) の配列をポイントしTest::test()
ます。
派生オブジェクトは、Base+Derived で構成されます。つまり、バイトの最初のチャンクが Base オブジェクトであり、残りが Derived であることを意味します。もしそうなら、私たちの objTest の例では、2 番目は 3 つの関数ポインタ (1 番目と、および)_vptr
を指すはずです。しかし、代わりに、最初のが の関数ポインタを指していることがわかります。Base2::fun1()
Base2::func1()
Test::test()
_vptr
Test::test()
質問:
1.この動作はコンパイラ固有のものですか?
2.規格はこの動作について何か言及していますか? それとも私の理解は完全に間違っていますか?
c++ - オブジェクトを持たないクラスの vtable を取得する
ここで最初に説明したのと同様のシステムを実装しようとしています。つまり、実行時にオブジェクトの動作を変更するために vtable の変更を (悪用) 使用することです。これは、私が取り組んでいる C++ プロジェクトで効率的な型ジェネリック ラッパーを作成する試みの一部です。
例では、アクセスできない場合は、次のように使用して vtablememcpy()
とthis
ポインターをコピーします。
ただし、この方法には問題があります。vtable のコピー元となるターゲット クラスのオブジェクトがなく、作成する必要がないタイプもあります。
そのクラスのオブジェクトなしで、特定のクラスのオブジェクトに埋め込まれた vtable にアクセスする方法はありますか?
ある程度移植性があれば望ましいのですが、私はこれがコンパイラ固有であることを大部分辞任しました。そのため、他に選択肢がない場合は、GCC/G++ のみの方法が受け入れられます。また、かなり標準的な OS とアーキテクチャでこれを構築することだけに関心があると仮定しましょう。
私はC++ 11を使用していますが、それが何らかの形でこれを支援する必要があります。
編集:完全に明確にしたいのですが、この種の行動がどれほど危険であるかを知っています. 私は、このアイデアと、おそらく非常に管理された状況でのその狭いアプリケーションに興味がありますが、私の紹介が示唆するものにもかかわらず、それが製品ソフトウェアにとって良いアイデアであるということよりも興味があります。
c++ - 多重継承の場合の vptr の選択
これは以前の多くの質問に似ていますが、私が答えを見つけることができなかった何かを尋ねます.
具体的には、b2_fn() に到達するために、Base2 の Derived の vtable の vptr を b2 がどのように指すのでしょうか? gcc から memlayout ダンプを見てみましたが、よくわかりませんでした。
c++ - memcpy 派生クラスから基本クラスへ、なぜ依然として基本クラス関数と呼ばれるのか
Inside the C++ Object Modelを読んでいます。セクション 1.3 で
では、なぜそうなのかというと、
呼び出されたrotate()のインスタンスはBearのインスタンスではなく、ZooAnimalのインスタンスですか? さらに、メンバごとの初期化によって、あるオブジェクトの値が別のオブジェクトにコピーされる場合、za の vptr が Bear の仮想テーブルをアドレス指定しないのはなぜですか?
2 番目の質問に対する答えは、あるクラス オブジェクトの初期化と別のクラス オブジェクトへの割り当てにコンパイラが介入することです。コンパイラは、オブジェクトに 1 つ以上の vptr が含まれている場合、それらの vptr 値がソース オブジェクトによって初期化または変更されないようにする必要があります。
そこで、以下のテストコードを書きました。
結果_
私の質問は、b_memcpy がまだ Base::vfunc() と呼ばれている理由です。