記憶がどのように流れるかについて、しかし、私は理由を理解できませんでした

こんにちは、habracheloveki様。



この短い投稿では、アプリケーション(Windowsのリーダー)の開発中に出会ったいくつかのポイントを共有したいと思います。 これはDirectXについてのもので、奇妙なメモリリークのように思えました。



自分で問題を作成するにはどうすればよいですか?



ページのコンテンツを表示するには、DirectXを使用することにしました。 アイデアはシンプルでした。最初にテキストで2Dテクスチャを作成し、次に事前に準備したテクスチャを使用して3Dモデルを表示します。 これにより、3Dページめくりアニメーションを行うことができます。



このようなもの:







ストアへのアプリケーションのリリースの時点で、私は普遍的な賞賛を期待していました。 しかし、そこにありました。 ユーザーは不満でした。 状況の分析は、記憶が流れていることを示しました。 そして、非常によく流れます。 しかし、なぜですか? これは長い間理解できませんでした。

Windows 8.1およびWindows Phone 8.1のアプリケーションが「クローズ」中に完全にアンロードされないという事実を考えると、メモリリークが蓄積されました。



漏れを見つけるプロセスはまったく面白くありませんでした。 しかし、結果は私には奇妙に思えました。



私にとって奇妙に思えたのは何ですか?



レンダーターゲットリソース(翻訳方法がわからない)と深度バッファの解放



次のオブジェクトは、3Dシーンの1つのフレームを表示するために使用されます。



Microsoft::WRL::ComPtr<ID3D11RenderTargetView> m_renderTargetView; Microsoft::WRL::ComPtr<ID3D11DepthStencilView> m_depthStencilView;
      
      





さらに、シーン表示メソッドのどこかで、次のコードのようなものを使用します。



 ID3D11RenderTargetView *const targets[1] = { m_renderTargetView.Get() }; m_d3dContext->OMSetRenderTargets(1, targets, m_depthStencilView.Get());
      
      





リソースを解放する必要があります。 そして、この投稿の原因となった問題の1つが潜んでいます。

書くだけ:



 m_renderTargetView = nullptr; m_depthStencilView = nullptr;
      
      





十分ではありません。 内部のm_d3dContextには、レンダーターゲットと深度バッファーへのリンクがあります。

つまり 目標としてコンテキストに何も示す必要はありません。



 m_d3dContext->OMSetRenderTargets(0, nullptr, nullptr);
      
      





問題は、次のようにするとメモリリークが発生することです。



 m_d3dContext->OMSetRenderTargets(0, nullptr, nullptr); m_renderTargetView = nullptr; m_depthStencilView = nullptr;
      
      





状況を修正するには、指示の順序を変更するだけです。



 m_renderTargetView = nullptr; m_depthStencilView = nullptr; m_d3dContext->OMSetRenderTargets(0, nullptr, nullptr);
      
      





これは私が理解していない最初の「奇異」です。 誰かがこれが起こる理由を教えてくれたら嬉しいです。



テクスチャリソースリリース



2番目の「奇異」はテクスチャに関連しています。 または、シェーダーリソースを使用します。

事実は、これが好きなら:



 Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> texture = ... m_d3dContext->PSSetShaderResources(0, 1, &texture);
      
      





そうする必要があります:



 ID3D11ShaderResourceView* empty = NULL; d3dContext->PSSetShaderResources(0, 1, &empty);
      
      





そうしないと、テクスチャを「削除」しても、テクスチャは解放されません。



 texture = nullptr;
      
      





つまり、シェーダーリソースを削除(リリース)する前に、それらを解放(バインド解除)する必要があります。



原則として、最初の「奇妙さ」を実現した後、2番目はもはやそうではないようです。

それにもかかわらず、これは私には明らかではないようでした。



PS:現在、メモリリークの問題は修正されており、ユーザーの怒りは徐々に慈悲に変わっています。



All Articles