2

クラスのプライベート変数で非常に奇妙な動作に遭遇しました。

問題の説明:クラスlapi_xmeef_tableのプライベートメンバー "current"の値が、メンバー関数の最後で異常に変更されました。

クラス1:lapi_xmeefクラス2:lapi_xmeef_table(lapi_xmeefのフレンドであるため、lapi_xmeefのプライベート変数に直接またはパブリックインターフェイスを介してアクセスできます)

class lapi_xmeef {
  friend class lapi_xmeef_table;
  ...
  short bias_frag_layer;
  int bias_frag_index;
  ...
  public:
    // Add constructor
    lapi_xmeef();
    // Add public interface
    ...
    void bias_frag(int *li, int *fi);

};

class lapi_xmeef_table {
  private:
    lapi_xmeef *current;
    ...
  public:
    lapi_xmeef_table(Lapi_ctl *ctl, int num_layer);
    ...
    void get_bias(int *li, int *fi);
    ...
}; 

「current」と呼ばれるlapi_xmeef_tableのプライベート変数は、現在のイテレータ(クラスlapi_xmeef)です。

メンバー関数は読み取り専用であり、プライベートメンバーから2つの値をコピーします。以下のように表示

void lapi_xmeef::bias_frag(int *li, int *fi)
{
   *li = (short)bias_frag_layer;
   *fi = bias_frag_index;
}

問題の関数と変数:

void lapi_xmeef_table::get_bias(int *li, int *fi)
{
// current is (lapi_xmeef *) 0x2a9a93c7f0 (a valid address)
  current->bias_frag(li, fi);
// current is (lapi_xmeef *) 0x2a000000df (a invalid address)
}

関数を呼び出す前のcurrentは(lapi_xmeef *)0x2a9a93c7f0(有効なアドレス)後のcurrentは(lapi_xmeef *)0x2a000000df(無効なアドレス)

これは、メンバー関数が呼び出されるたびに発生するわけではありません。この奇妙な動作の前に、問題なく何度も呼び出されます。

次回、現在のメンバーにアクセスしているときに、無効なアドレスが逆参照されるため、セグメンテーション違反が発生します。

今私の解決策は、メンバー関数を呼び出す前にcurrentの値を保存し、呼び出した後にそれを復元するための一時ポインターを持っていることです。できます。

void lapi_xmeef_table::get_bias(int *li, int *fi)
{
  lapi_xmeef *temp = current;
  current->bias_frag(li, fi);
  current = temp;
}

しかし、私は本当にこのトリッキーな方法の代わりにそれを修正する理由と方法を知りたいです。

同じであると予想されるプライベート変数の値が変更されるのはなぜですか?

プライベートバリバールへのアクセス方法に問題はありますか?プレフィックスが必要ですか、それとも「これ」というポイントが必要ですか?私はこれを試しました->current->bias_frag(li、fi); これは役に立ちません。

前もって感謝します。

4

1 に答える 1

1

発生する可能性が高いのは、意図しないポインタエイリアシングが発生していることです。liまたはポインタの1fiつがと同じ場所を指している&currentため、間接参照して内部でそれらに割り当てると、bias_frag誤って上書きcurrentまたはその一部になります。

これを修正するには、データフローを逆方向にトレースして、エイリアスポインタを取得している理由を理解する必要があります。手始めに、コンパイラの警告レベルを上げて、すべての警告を修正します。

の価値を保存して復元することで回避しようとしないでくださいcurrent。これは、はるかに大きな問題に対する単なる包帯であり、長期的な解決策ではありません。あなたはすでに未定義の行動の地に入っており、自分自身を掘り起こそうとしてもうまくいきません。

于 2012-11-15T15:49:45.810 に答える