16

私は次のコードを持っています:

void MyClass::onOpenModalBtnClicked() {
    uiManager->load(L"data/ui/testmodal.json");
    std::shared_ptr<UIElement> modal = uiManager->getElementById("loginModal");

    if(modal) {
        modal->getElementById("closeButton")->onClicked = [modal]() {
            modal->hide();
        };
    }
}

onClickedこれは正常に機能し、ボタンをクリックするとモーダルが閉じられますstd::function

アプリの冒頭にもこれがあります:

#if defined(DEBUG) | defined (_DEBUG)
    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif

これにより、アプリの終了時にメモリ リークが出力されます。

上記のコードでは、多くのメモリ リークが発生します。コードを以下のように変更すると、それらはすべてなくなります。

void MyClass::onOpenModalBtnClicked() {
    uiManager->load(L"data/ui/testmodal.json");
    std::shared_ptr<UIElement> modal = uiManager->getElementById("loginModal");

    if(modal) {
        modal->getElementById("closeButton")->onClicked = [this]() {
            uiManager->getElementById("loginModal")->hide();
        };
    }
}

by 値を渡すとshared_ptrref カウントが 1 増加し、この参照が範囲外に出ないか、メモリ リークが報告された後に範囲外になると想定しています。そのため、shared_ptr を使用した後、ラムダ内でリセットを呼び出そうとしましたが、次のコンパイラ エラーが発生しました。

Error 1 error C2662: 'void std::shared_ptr<_Ty>::reset(void) throw()' : cannot convert 'this' pointer from 'const std::shared_ptr<_Ty>' to 'std::shared_ptr<_Ty> &'

問題は、キャプチャされたものをどのように使用して、modalそれらのメモリ リークを取得しないかということです。

編集:mutableラムダ に追加することでコンパイルエラーを取り除きました。

if(modal) {
    modal->getElementById("closeButton")->onClicked = [modal]() mutable {
        modal->hide();
        modal.reset();
    };
}

閉じるボタンをクリックしてアプリを閉じると、リセットによってその参照が消去されるため、メモリ リークは発生しません。しかし、ボタンがクリックされない場合でも、リークが発生します。

4

2 に答える 2