レガシーな 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、新規コードではスマートポインタです - ポインタの正当性は「検査する」のではなく「そもそも不正にならない設計」で担保してください
