2025/09/09 22:04 The case of the crash on a null pointer even though we checked it for null

やっほー、ロボ子!今日も張り切ってITニュースを斬っていくのじゃ!

はい、博士!本日もよろしくお願いいたします。

今日はC++/WinRTのクラッシュに関する話題じゃ。`IVectorView<T>::Size`をnullポインタに対して呼び出すとクラッシュするらしいぞ。

`IVectorView<T>::Size`ですか。それは、コレクションの要素数を取得するメソッドですよね。

そうじゃ!クラッシュ箇所は`winrt::impl::consume_Windows_Foundation_Collections_IVectorView<winrt::Windows::Foundation::Collections::IVectorView<int>, int>::Size+0x30`らしい。

スタックトレースから、かなり深い場所で発生していることが分かりますね。

原因は`Widget::InitializeNodesAsync`内で、`std::optional<winrt::IVectorView<int32_t>> numbers`が値を持たない状態で`(*numbers).Size()`を呼び出したことらしいぞ。

`std::optional`が空の状態で、参照外しを行った、ということですね。

そうそう。`if (numbers == nullptr)`というチェックが期待通りに動かなかったのがミソじゃ。

`std::optional`が`std::nullopt`と等しいかをチェックするものではないからですね。

その通り!修正案としては、`if (!numbers.has_value())`で`std::optional`が値を持つかどうかを正しく判定するか…

もしくは、`std::optional`の使用を避けて、`numbers`を直接`winrt::IVectorView<int32_t>`として宣言し、初期値を`nullptr`とする方法ですね。

後者の方が、`GetMagicNumbers`がnullポインタを返す場合にも対応できるから推奨らしいぞ。

なるほど。より安全なコードになりますね。

ただ、実際には`GetMagicNumbers`はnullポインタを返さないから、元のコードは起こりえない状況に対するチェックだった、というオチ付きじゃ。

そうだったんですね。少し残念です。

まあ、安全なコードを書くのは良いことじゃ!…ところでロボ子、`std::optional`って、お菓子のオプショナルツアーみたいじゃな。

博士、それは少し違います。でも、お菓子のオプショナルツアーも楽しそうですね!
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。
