1

Visual Studio 2010 で、NULL オブジェクトでメンバー関数を呼び出すバグを自動的にキャッチする方法はありますか? おそらく、すべてのメンバー関数の始まりに適切なアサーションを置くフラグはありますか?

デフォルトの動作では、黙ってそれを受け入れ、フィールドがアクセスされたときにのみクラッシュします。ただし、場合によっては、元のエラーよりもずっと後の場合があります。


編集:ポインターでメンバー関数を呼び出すと、未定義の動作が呼び出されることを知っています。NULL根絶したいのは私のコードのバグです。Visual Studio に、私を支援してくれる非標準のツールがあることを願っています。

4

5 に答える 5

2

いいえ、しかし、RAII を完全に採用し、C++11 スマート ポインターのみを使用する場合 (明示的に削除を呼び出すことはありません)、そのようなバグに遭遇することはほとんどありません。

于 2013-03-10T14:03:28.327 に答える
2

いいえ、それは役に立たないでしょう。

NULLポインターでメンバー関数を呼び出すと、未定義の動作が呼び出されます。名前が示すように、この時点で動作を確認することはできません。

具体的には:

void MyObject::foo() {
    if (this) { throw std::logic_exception("this is NULL"); }

    std::cout << "Hello, world!\n";
}

準拠するコンパイラによって次のように合理的に変更できます。

void MyObject::foo() {
    std::cout << "Hello, world!\n";
}

結局のところ、標準thisは が最初から null にならないことを保証しているからです!

ただし、できることは、「生の」ポインターに依存することではありません。

template <typename T>
class Pointer {
public:
    Pointer(): _ptr(nullptr) {}
    Pointer(T* t): _ptr(t) {}

    T* operator->() const { assert(_ptr); return _ptr; }
    T& operator*() const { assert(_ptr); return *_ptr; }

private:
    T* _ptr;
};

そして、ポインターのように使用します。

int main() {
    Pointer<MyObject> value = container.find("Element");
    value->foo();
}

foonull の場合は、への呼び出しが試行される前にアサートが発生します。

于 2013-03-10T14:38:01.377 に答える
1

が NULLかどうかを確認できthisますが、MSVS で実行している場合はDebugBreak、デバッグ ブレークを強制してスタックを調査するために - オプションを検討する必要があります。これは、最も効果的なバグにつながる可能性があります。デバッガーなしでそのコードを実行すると、デバッガーが続行するように指示できないため、アプリケーション自体がハングするため、リリース コンパイルからチェックを削除しました。その問題を回避するには、isDebuggerPresent() について考えることができます。

#ifdef DEBUG
#define CHECK() if (this==NULL) DebugBreak();
#else
#define CHECK() 
#endif

IsDebuggerPresent:

MSDN の DebugBreak:

于 2013-03-10T14:40:23.670 に答える
0

これをチェックするための特別なオプションは知りませんが、簡単にマクロを書くことができます:

 #define CHECK_THIS()  assert(this)

また

 #define CHECK_THIS() do { if (this == NULL) { std::cerr << "'this' is NULL at " \
                             << __FILE__ << ":" << __LINE__ << " in " << __func__; \
                             exit(2); } while(0)

(「do - while」を使用しているため、他のifステートメントなどに干渉することなくどこにでも配置できます)。

CHECK_THIS()次に、関連する関数を追加します。

于 2013-03-10T14:01:51.480 に答える
0

自動 - わかりませんが、いつでもアサートを使用できます。

assert(this);

それthisが「呼び出し先」クラスインスタンスを参照するキーワードであると考えると、どのようにNULLになることができますか? NULL ポインターを介して呼び出しますか?

于 2013-03-10T14:02:36.160 に答える