0

さて、私は Map を使用してあらゆる種類のポインター (void*) を格納しており、それはスコープ オブジェクトで使用されています。これがスコープクラスです。

class Scope
{
  protected:
    Scope * parent;
    MyMap* map;
  public:
    virtual void setParent(Scope* p)=0;
    virtual Scope* getParent()=0;
    virtual void setOwner(void * owner)=0;
    virtual void * getOwner()=0;
    virtual Symbol * get(char* name)=0;
    virtual Symbol * get(char* name, Signature * sig)=0;
    MyMap* getMap()const;
 };

2つのクラスがありOrderedScope、クラスDisorderedScopeを実装していScopeます。

私のプロジェクトでは、すべてのデータを void* として保存しようとしており、それらを取得して適切な型にキャストしています。オブジェクトをその型にキャストすると、一部のデータが失われていることがわかりました。ここに私が得たものの写真があります。 ここに画像の説明を入力

Packageクラスにスコープがあることを明確にするためだけに。そして、そのスコープにFunctions 型のオブジェクトを格納しています。したがって、関数を追加する場合は、最初にパッケージ オブジェクトを取得してから、その関数を使用しaddて新しい関数を挿入する必要があります。

問題を正しく示したかどうかはわかりませんが、そうであることを願っています。あなたの助けに感謝します。

4

1 に答える 1

2

void ポインターは、そのポインターに対するコンパイラーの型チェックを無効にするため、危険なメカニズムです。したがって、間違い (void ポインターを間違った型にキャストするなど) を行った場合、コンパイル時エラーは発生せず、データの破損などの実行時の誤動作として問題に気付くだけです。

したがって、質問に答えるには、void ポインターを使用してデータの破損を回避したい場合は、void ポインターを (SomeType *) にキャストするときに、void ポインターが指すメモリ位置を非常によく確認する必要があります。 to には、実際には有効な (SomeType *) が含まれており、他には何も含まれていません。特に、void ポインターが指している (SomeType *) がまだ有効であり、void ポインターを作成してからキャストしようとするまでの間に削除/解放されていないことを確認する必要があります。これを使って。また、void ポインターと多重継承を組み合わせるときに発生する可能性のある落とし穴に注意する必要があります。、複数のスーパークラスを持つクラスは、表示しているスーパークラスに応じて異なる「this」ポインターを持つことができるため、void-pointer へのキャストは、正しい「this」ポインターを自動的に保存しません (コンパイラーができるため)後でどの「this」ポインターに関心があるかわかりません)。

これはすべて実行可能ですが、プログラムのロジックは常に 100% 正しくなければなりません。すべてを非常に慎重にコーディングし、コードを調べてエラーを探し、徹底的にテストする以外に、これへの近道はありません。valgrind や Purify などのコード チェッカーも、コードを実行しただけでは症状が明確ではないエラーを見つけるのに役立ちます。

とはいえ、上記のコメント者は正しいです。一般に、void ポインターを使用するよりも優れた/安全な代替手段があります。これらの代替手段 (テンプレートや共通の基本クラスなど) は、実行時にエラーを 1 つずつ探し出すのではなく、コンパイル時にコンパイラにエラーを検出させるため、エラーが発生しにくくなります。 . また、生のポインターではなくスマート ポインター (shared_ptr など) を使用することを検討してください。これにより、オブジェクトの有効期間の処理がコンパイラーにオフロードされ、ハンドロール コードよりも確実かつ一貫してそのタスクを処理できるようになります。

于 2013-05-20T14:59:03.363 に答える