void-pointerが指しているメモリの最初の4バイトを調べて、これが有効なvtableのアドレスであるかどうかを確認したいと思います。
あなたはそれを行うことができますが、それが機能するという保証はありません。void*がvtableを指すかどうかさえわかりません。前回これを調べたとき(5年以上前)、一部のコンパイラは、インスタンスが指すアドレスの前にvtableポインタを格納したと思います*。
私はこれがプラットフォームであることを知っています、おそらくコンパイラバージョン固有です、
使用する最適化などによっては、コンパイラオプション固有の場合もあります。
しかし、それは私がアプリケーションを前進させ、限られた期間(たとえば3年)ですべてのボイドポインターを取り除くのに役立つ可能性があります。
これは、アプリケーションを前進させるために表示できる唯一のオプションですか?他の人を考慮しましたか?
アプリケーション内のすべてのvtableのリストを取得する方法はありますか?
いいえ :(
または、ポインタが有効なvtableを指しているかどうかを確認する方法。
標準的な方法はありません。できることは、お気に入りのデバッガーでいくつかのクラスポインターを開き(またはメモリをバイトにキャストしてファイルに記録し)、それを比較して意味があるかどうかを確認することです。それでも、データ(またはアプリケーション内の他のポインター)が(バイトとしてキャストされたときに)十分に類似していないため、好きなコードを混乱させるという保証はありません。
そして、vtableを指すそのインスタンスが既知の基本クラスを継承するかどうか。
いいえ、もう一度。
ここにいくつかの質問があります(あなたはすでにそれらを考慮しているかもしれません)。これらへの回答はあなたにもっと多くの選択肢を与えるかもしれません、あるいは私たちに提案する他のアイデアを与えるかもしれません:
コードベースの大きさはどれくらいですか?グローバルな変更を導入することは可能ですか、それともそのために機能を広めることができますか?
すべてのポインターを均一に扱いますか(つまり、プラグインして独自のメタデータを追加できる共通のポイントがソースコードにありますか?)
ソースコードで何を変更できますか?(メモリ割り当てサブルーチンにアクセスできる場合、またはたとえば独自のサブルーチンをプラグインできる場合は、独自のメタデータをプラグインできる可能性があります)。
コードのさまざまな部分でさまざまなデータ型がvoid*にキャストされている場合、後でそれらのポインターに何があるかをどのように決定しますか?void *を識別するコードを使用して、それらがクラスであるかどうかを判断できますか?
あなたのコードベースはリファクタリングの方法論を可能にしますか?(コードの一部に代替実装をプラグインし、最初の実装を削除してすべてをテストすることにより、小さな反復でリファクタリングします)
編集(提案された解決策):
次の手順を実行します。
メタデータ(ベース)クラスを定義する
メモリ割り当てルーチンを、標準/古いルーチンを参照するだけのカスタムルーチンに置き換えます(コードがカスタムルーチンで引き続き機能することを確認します)。
割り当てごとに、割り当てthe requested size + sizeof(Metadata*)
ます(そして、コードが引き続き機能することを確認します)。
割り当ての最初の バイトを、簡単にテストできる標準のバイトシーケンスに置き換えsizeof(Metadata*)
ます(私は0xDEADBEEF:Dに部分的です)。次に、[allocated address] + sizeof(Metadata*)
アプリケーションに戻ります。割り当て解除時に、受信したポインタを取得し、 `sizeof(Metadata *)でデクリメントしてから、システム/前のルーチンを呼び出して割り当て解除を実行します。これで、特に各割り当てのメタデータ用に、コードに追加のバッファーが割り当てられました。
メタデータを使用する場合は、メタデータクラスポインターを作成/取得してから、0xDEADBEEFゾーンに設定します。メタデータをチェックする必要がある場合reinterpret_cast<Metadata*>([your void* here])
は、それをデクリメントしてから、ポインタ値が0xDEADBEEF(メタデータなし)か何か他のものであるかどうかをチェックします。
このコードはリファクタリングのためだけに存在する必要があることに注意してください。本番コードの場合、速度が遅く、エラーが発生しやすく、一般的に本番コードにしたくないその他の悪いことがあります。このすべてのコードを、メタデータクラスが製品リリースの光を見ることができないマクロに依存するREFACTORING_SUPPORT_ENABLED
ようにします(ビルドのテストを除く)。