問題タブ [vtable]
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++ - vtable を使用してクラス タイプを決定する方法
私は最近、C/C++ が主要な言語であるポジションの面接を受けました。ある質問の中で、vtable を使用して、階層内のどのクラスのベース ポインターが実際に格納されているかを判断できると言われました。
たとえば、あなたが持っている場合
インスタンス化A * pFoo = new B()
すると、vtable を使用して pFoo に A または B のインスタンスへのポインタが含まれているかどうかを判断することは本当に可能ですか?
c++ - クラス階層をダンプするためのVisualC++コンパイラオプション
GCCの-fdump-class-hierarchyと同等のコンパイラオプションがMSVisualC ++にありますか?つまり、仮想関数テーブルのレイアウトを表示します。
c++ - 既存のすべてのvtableのリストを取得する
私のアプリケーションにはかなりの数のvoidポインタがあります(これは歴史的な理由によるもので、アプリケーションは元々純粋なCで書かれていました)。私のモジュールの1つでは、voidポインターが、既知の基本クラスから継承できるクラスのインスタンスを指していることを知っていますが、100%確信することはできません。したがって、voidポインタでdynamic_castを実行すると、問題が発生する可能性があります。おそらく、voidポインターはプレーン構造体を指していることさえあります(したがって、構造体にvptrはありません)。
void-pointerが指しているメモリの最初の4バイトを調べて、これが有効なvtableのアドレスであるかどうかを確認したいと思います。これはプラットフォームであり、コンパイラバージョン固有である可能性もありますが、アプリケーションを前進させ、限られた期間(たとえば、3年)ですべてのボイドポインタを取り除くのに役立つ可能性があります。
アプリケーション内のすべてのvtableのリストを取得する方法、またはポインターが有効なvtableを指しているかどうか、およびvtableを指しているそのインスタンスが既知の基本クラスを継承しているかどうかを確認する方法はありますか?
java - 「java.lang.IncompatibleClassChangeError: vtable stub」の原因は何ですか?
「java.lang.IncompatibleClassChangeError: vtable stub」の原因は何ですか? 私たちのアプリケーションでは、このエラーがランダムに表示されることはほとんどありません (これまでに 2 回だけで、何度も実行しています)。アプリを再起動しても、再構築せずに同じ jvm/jar を使用しても、すぐには再現できません。
ビルド プロセスに関しては、すべてのクラス/jar をクリーンアップして再構築するため、あるクラスに変更を加えて他の依存クラスを再コンパイルしなかった場合に他の人が遭遇した問題とは異なります。
これは、IncompatibleClassChangeError に関連する他のいくつかの質問とは異なります。「vtable スタブ」について言及しているものはありません。実際、「IncompatibleClassChangeError "vtable stub"」で検索すると、Googleで検索結果が驚くほど少ないです。
編集:
- JDK 1.6.0_16 を使用。
- Java シリアライゼーションは使用していません。
- バイトコード操作は行っていません。
- 前述のとおり、「クリーン ビルド」を行っているため、以前のビルドから残っているクラスはありません。
c++ - 仮想メンバー関数の出力アドレス
仮想メンバー関数のアドレスを出力しようとしています。関数を実装するクラスがわかっている場合は、次のように記述できます。
しかし、私はこのようなことをしたい:
ただし、これはコンパイルされません。実行時に vtable 内のアドレスを調べて、このようなことを行うことは可能ですか?
c++ - 仮想継承によるC++vtableの解決
私はC++と仮想継承、特にベースクラスと子クラスの間でvtableの競合が解決される方法に興味がありました。それらがどのように機能するかについての詳細を理解するふりをするつもりはありませんが、これまで私が輝いていたのは、それらがその解像度による仮想関数の使用によって引き起こされる小さな遅延であるということです。私の質問は、基本クラスが空白であるかどうかです。つまり、その仮想関数は次のように定義されます。
これは、選択できる関数のセットが1つしかないため、解像度が不要であることを意味しますか?
これがばかげた質問である場合は、私を許してください-私が言ったように、私はvtablesがどのように機能するかを理解していないので、私は本当にこれ以上よくわかりません。
編集
したがって、2つの別個の子クラスを持つ抽象クラスがある場合:
子クラスから関数を呼び出すときに、単一の継承のないクラスと比較して、パフォーマンスへの影響はありませんか?
delphi - DelphiのCOMメソッドオフセット
Delphiで、COMメソッドのアドレスを確認するにはどうすればよいですか?オフセットをハードコーディングできます
しかし、私は象徴的な名前を使用したいと思います。以下は明らかに機能しません:
ありがとう!
c++ - vtable実装を使用したc++仮想呼び出しでのマルチスレッド競合状態の疑い
vtable動的ディスパッチング実装(vtableポインターが仮想メソッドを持つオブジェクトの非表示メンバーとして格納されている)の仮想メソッド呼び出しを含む特定のC ++マルチスレッド状況で、競合状態が発生する可能性があるのではないかと疑っています。これが実際に問題であるかどうかを確認したいのですが、参照のフレームを想定できるように、boostのスレッドライブラリを指定しています。
オブジェクト「O」にboost::mutexメンバーがあり、そのコンストラクタ/デストラクタとメソッド全体がスコープロックされているとします(Monitorの同時実行パターンと同様)。スレッド「A」は、外部同期なしで(つまり、他のスレッドと同期できる「新しい」操作を囲む共有ミューテックスなしで)ヒープ上にオブジェクト「O」を構築します。ただし、「内部」がまだ存在することに注意してください。 、そのコンストラクタのスコープをロックする「監視」ミューテックス)。次に、スレッドAは、同期されたメカニズム(たとえば、同期されたリーダー/ライターキュー)を使用して、「O」インスタンス(作成したばかり)へのポインターを別のスレッド「B」に渡します(注:へのポインターのみオブジェクト自体ではなく、オブジェクトが渡されます。建設後、
スレッド「B」は、同期されたキューからオブジェクト「O」のポインタ値を読み取り、その後すぐにキューを保護しているクリティカルセクションを離れます。次に、スレッド「B」はオブジェクト「O」に対して仮想メソッド呼び出しを実行します。ここで問題が発生する可能性があると思います。
動的ディスパッチの[かなりありそうな]vtable実装での仮想メソッド呼び出しについての私の理解は、オブジェクトの非表示メンバーとして格納されているvtableポインターを取得するために、呼び出しスレッド「B」がポインターを「O」に逆参照する必要があるということです。 、およびこれはメソッド本体に入る前に発生します(当然、実行するメソッド本体は、オブジェクト自体に格納されているvtableポインターにアクセスするまで、安全かつ正確に決定されないため)。前述のステートメントがそのような実装に当てはまる可能性があると仮定すると、これは競合状態ではありませんか?
vtableポインターは、メモリの可視性を保証する操作(つまり、オブジェクト「O」のメンバー変数ミューテックスの取得)の前に、スレッド「B」によって(ヒープ内にあるオブジェクト「O」へのポインターを参照解除することによって)取得されるためです。 、それでは、「B」が、「A」がオブジェクト「O」の構造に最初に書き込んだvtableポインタ値を認識するかどうかは定かではありません。(つまり、代わりにガベージ値を認識し、未定義の動作を引き起こす可能性がありますよね?)。
上記が有効な可能性である場合、これは、スレッド間で共有される排他的に内部同期されたオブジェクトで仮想メソッド呼び出しを行うことが未定義の動作であることを意味しませんか?
また、同様に、標準はvtableの実装に依存しないため、仮想呼び出しの前にvtableポインターが他のスレッドに安全に表示されることをどのように保証できますか?コンストラクター呼び出しと、少なくとも各スレッドでの最初の仮想メソッド呼び出しを外部で同期(たとえば、「共有ミューテックスlock()/ unlock()ブロックで囲む」のように「外部」)できると思います。しかし、これはひどく不調和なプログラミングのようです。
したがって、私の疑いが真実である場合、おそらくより洗練された解決策は、メンバーのミューテックスをロックし、その後仮想呼び出しに転送するインラインの非仮想メンバー関数を使用することです。しかし、それでも、コンストラクターがコンストラクター本体自体を保護するlock()とunlock()の範囲内でvtableポインターを初期化することを保証できますか?
誰かが私がこれを片付けて私の疑いを確認/否定するのを手伝ってくれるなら、私は非常に感謝するでしょう。
編集:上記を示すコード
--ポイント(4)で、「スレッドA」がメモリに書き込んだvtableポインタ値が「スレッドB」に表示されない可能性があるという印象を受けています。これは、コンパイラがvtableポインターがコンストラクターのロックされたmutexブロック内に書き込まれるようにコードを生成します。
たとえば、各コアに専用のキャッシュがあるマルチコアシステムの状況を考えてみます。この記事によると、キャッシュは一般的に積極的に最適化されており、キャッシュコヒーレンスを強制しているにもかかわらず、同期プリミティブが含まれていない場合は、キャッシュコヒーレンスに厳密な順序付けを強制しません。
おそらく私は記事の意味を誤解していますが、それは構築されたオブジェクトへのvtableポインターの「A」の書き込み(そしてこの書き込みがコンストラクターのロックされたミューテックスブロック内で発生するという兆候がない)を意味するのではありません「B」がvtableポインターを読み取る前に、「B」によって認識されませんか?AとBの両方が異なるコア(core0の「A」とcore1の「B」)で実行される場合、キャッシュコヒーレンスメカニズムは、core1のキャッシュ内のvtableポインター値の更新(一貫性を保つ更新)を並べ替えることがあります。 「A」が書き込んだcore0のキャッシュ内のvtableポインターの値を使用して、「B」の読み取り後に発生するようにします...記事を正しく解釈している場合。
c++ - C++ の継承コスト
例として、次のスニペットを取り上げます。
ご覧のとおり、この関係には仮想関数は存在しません。これが事実であるため、言語に関する限り、次の仮定は正確ですか?
- では仮想関数テーブルは作成されません
Bar
。 sizeof(Bar) == sizeof(Baz)
基本的に、私はこれを行うことに対して何らかのペナルティを支払うかどうかを理解しようとしています. 私の最初のテスト (単一のコンパイラーではありますが) では、私のアサーションが有効であることが示されていますが、これが私のコンパイラーのオプティマイザーなのか、それとも言語仕様なのかはわかりません。
visual-c++ - vtable 内のオーバーロードされたメソッドの順序 (win32 上)
vtable 内のオーバーロードされたメソッドの順序は、win32 コンパイラ間で常に同じですか?
問題: 「インターフェース」(データ メンバーを持たない純粋な仮想クラス) があります。これらは、さまざまなコンパイラからのポインターを介して使用できます (クライアントは、標準の c dll ファクトリ メソッドを呼び出してポインターを取得します)。これは、1 つのメソッドを除いて、さまざまなコンパイラ (例: borland で作成されたクライアント、Visual C++ で作成されたインターフェイス dll) で正常に機能します。このメソッドは、戻り値は同じですが、パラメータが異なります。このメソッドには 4 つのバージョンがあります。このメソッドを同じように呼び出しても、クライアントをコンパイルしたコンパイラによって異なる結果が返されます。アセンブラコードをざっと見てみると、vtable に別のオフセットがあるように見えました (私はアセンブラを読むのが得意ではありません)。
今はわかりません-原因を見つけたのでしょうか、それともボーランドがビジュアルスタジオとは異なるvtableを処理しているだけで、すべてが正しいので、他の場所を検索する必要があります.
よろしくお願いします。回答ありがとうございます。
トバイアス