レガシーなMFCコードの中にIsBadReadPtrやIsBadWritePtrを使ったポインタチェックが残っていることがあります。一見安全そうに見えますが、Microsoftはこれらの関数を使わないことを推奨しています。
この記事では、なぜ使ってはいけないのかと、代わりに何をすべきかを解説しています。

なぜ非推奨なのか
IsBadReadPtr / IsBadWritePtrは、指定されたメモリ範囲にアクセスできるかを検査する関数です。内部的には構造化例外処理(SEH)でアクセス違反を捕捉して結果を返します。
この仕組みには、致命的な問題が3つあります。
問題1:ガードページを踏み潰す
Windowsはスレッドごとのスタック拡張や一部の保護にガードページ(PAGE_GUARD)を使っています。IsBadReadPtrのような「読めるか試す」APIは、その保護ページに触れて例外を消費する可能性があり、特に別スレッドのスタック拡張タイミングと競合すると挙動を壊します。
問題2:マルチスレッドで競合する
IsBadReadPtrがFALSE(読み取り可能)を返した瞬間に、別のスレッドがそのメモリを解放するかもしれません。チェックした時点と使う時点で状態が異なる(TOCTOU: Time of Check to Time of Use)ため、結果を信頼できません。
問題3:バグを隠す
不正なポインタが渡されたということは、すでにバグが存在しています。IsBadReadPtrでチェックして「ダメだったら何もしない」としても、バグの根本原因は放置されたままです。問題を隠してしまうことで、デバッグが困難になります。
Microsoftの公式見解
Microsoft LearnのIsBadReadPtrのページには、明確に次の記述があります。
This function is obsolete and should not be used. Despite its name, it does not guarantee that the pointer is valid or that the memory pointed to is safe to use.
「名前に反して、ポインタが有効であることも、メモリが安全に使えることも保証しない」と断言されています。

代わりに何をすべきか
ポインタの正当性をランタイムで検査しようとするのではなく、不正なポインタが渡されないコード設計にすることが正解です。
対策1:ASSERTで前提条件を明示する
void ProcessData(const MyStruct* pData)
{
ASSERT(pData != nullptr); // Debug ビルドで不正呼び出しを検出
if (pData == nullptr)
return;
// 本処理
pData->DoSomething();
}
ASSERTはDebugビルドで違反を即座に報告します。Releaseビルドでは消えるため、パフォーマンスへの影響はありません。
対策2:構造化例外処理(SEH)で保護する
どうしてもサードパーティのコールバックなど、信頼できないポインタを受け取る場面では、__try / __exceptで保護する方法があります。
__try
{
// 信頼できないポインタを使う処理
result = pCallback->Execute();
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
// アクセス違反が発生した場合のフォールバック
TRACE(_T("Callback caused access violation\n"));
result = E_FAIL;
}
ただし、これは最終手段です。SEHを多用するコードは、問題の隠蔽につながりやすいため注意してください。
対策3:スマートポインタを使う
新規コードではstd::unique_ptrやstd::shared_ptrを使うことで、そもそもダングリングポインタが発生しにくい設計にできます。
// 所有権が明確で、解放忘れがない
auto pData = std::make_unique<MyStruct>();
ProcessData(pData.get());
既存コードからIsBadReadPtrを除去する手順
- ソリューション全体でIsBadReadPtr / IsBadWritePtr / IsBadStringPtr / IsBadCodePtrを検索する
- 各呼び出し箇所で、なぜそのチェックが必要だったのかを調べる(不正ポインタの発生源を特定する)
- 発生源を修正できるなら修正し、チェックをASSERT(ptr != nullptr) + nullptrチェックに置き換える
- 発生源を修正できない場合(外部ライブラリ等)は、SEHで保護する
まとめ
- IsBadReadPtr / IsBadWritePtrはMicrosoftが公式に非推奨としています
- ガードページの破壊、TOCTOU競合、バグの隠蔽という3つの致命的問題があります
- 代替手段はASSERT + nullptrチェック、必要に応じてSEH、新規コードではスマートポインタです
- ポインタの正当性は、実行時に検査するのではなく、そもそも不正なポインタが生じない設計で担保するのが基本です
関連記事
- 【MFC】Memory Leak Detection: _CrtSetDbgFlagでリークを自動報告させる — 解放漏れを終了時に自動報告させ、確保箇所を特定する
