1

重複の可能性:
nullインスタンスでメンバー関数を呼び出すと、未定義の動作が発生するのはいつですか?

この質問の人は、「new」を使用してオブジェクトへのポインターを作成できませんでした。次に、このワイルドポインターを使用して、オブジェクトのメンバー関数を呼び出しました。

メンバー変数にアクセスすると(でmyPoint[i].x = xData;)、プログラムは失敗します。

それ以前ではなく、その場所で失敗するのはなぜですか?

4

3 に答える 3

3

問題の行は、 が参照される最初の位置thisです。

于 2012-10-26T17:09:28.617 に答える
1

そして、なぜですか?標準では、このプログラムには未定義の動作があると言われていますが、C++ ではクラスに 3 種類の関数があります。

// 1) static functions
class test {
public:
    static void foo( int n );
};

この例fooでは、同じシグネチャを持つグローバル関数のようなものですが、C++ ではアクセス チェックとその名前の規則が異なります。

// 2) normal member functions
class test {
public:
    void foo( int n );
};

ほとんどすべてのコンパイラでは、この関数は署名付きのフリー関数と同じであり、関数でアクセスしない限りvoid foo(foo* this, int n)、この関数を無効で呼び出すことはエラーではありません。あなたの記憶の。thisthis

// 3) virtual functions
class test {
public:
    virtual void foo( int n );
};

この場合class test、通常呼び出され、クラスvtableの各関数の実装への 1 つのポインターを含む追加の非表示メンバーが含まれますvirtual。この手法を使用すると、C++ は実行時に遅延バインディングを行うことができるため、この場合、fooコンパイラーを呼び出すときに次のように記述します。

this->vtable[foo_index]( this, n );

したがって、この場合、invalidはすぐにそれ自体を表示し、コール ポイントでthisアクセスするため、セグメンテーション違反や無効な命令などのエラーを生成する可能性があります。thisしたがって、ほとんどすべての実装でわかるように、無効なthisポインターを介して呼び出され、エラーを生成しないメンバー関数を持つことができます (this関数内でアクセスしない場合) virtual

ただし、上記の説明はコンパイラに完全に依存することを覚えておいてください。ただし、ほとんどすべてのコンパイラは上記のように実装しています

于 2012-10-26T17:54:55.593 に答える
1

Undefined Behaviorの詳細を読んで、例に基づいて構築する必要があります。

struct A { A(int i): _i(i) {} void print() const { printf("%d", _i); } int _i; };

void function(A* a) {
    if (a == 0) { printf("%s", "A is null!"); }
    a->print();
}

あなたは何を期待していますfunction(0);か?

A is null!それが印刷されて、プログラムがクラッシュすることを期待しているようですね。多分そうでないかもしれません。

コンパイラは実際には次のように処理を進める可能性があります。

  • a->print();:ここにaあることはできませんnull。それ以外の場合、このステートメントは無意味です
  • a == 0したがって、常にfalse
  • 関数は次のように書き直すことができますvoid function(A* a) { a->print(); }

そして、一般的な Linux プラットフォームでは、クラッシュ (SEGFAULT) が発生しますが、メッセージは表示されません... まったく!

これが、未定義の動作が最適化で行うことです。プログラムははるかに高速に実行されますが、わずかなミスで計り知れない方法で停止します。

于 2012-10-26T18:19:21.720 に答える